Compare commits

..

12 Commits

Author SHA1 Message Date
Dimitry Kolyshev
f6b704fb58 Merge remote-tracking branch 'origin/master' into 6263-custom-ups-cache 2023-11-24 09:55:04 +02:00
Dimitry Kolyshev
780d001cef all: imp locales 2023-11-24 09:54:42 +02:00
Dimitry Kolyshev
820bcf0e23 Merge remote-tracking branch 'origin/master' into 6263-custom-ups-cache
# Conflicts:
#	CHANGELOG.md
2023-11-23 11:16:54 +02:00
Dimitry Kolyshev
e7ca515630 Merge remote-tracking branch 'origin/master' into 6263-custom-ups-cache 2023-11-22 09:49:32 +02:00
Dimitry Kolyshev
23392d08b1 Merge remote-tracking branch 'origin/6263-custom-ups-cache' into 6263-custom-ups-cache 2023-11-22 09:49:10 +02:00
Dimitry Kolyshev
a09cd190c0 home: imp code 2023-11-22 09:48:43 +02:00
Ildar Kamalov
feb15745d2 client: move cache fields to the upstream tab 2023-11-21 17:27:38 +03:00
Ildar Kamalov
789060e4d4 client: add form fields 2023-11-21 16:28:03 +03:00
Dimitry Kolyshev
a700bfb42e Merge remote-tracking branch 'origin/master' into 6263-custom-ups-cache 2023-11-21 11:44:14 +02:00
Dimitry Kolyshev
7669419b59 home: imp code 2023-11-21 11:34:17 +02:00
Dimitry Kolyshev
4a9dc1d6c1 docs: http client docs 2023-11-20 15:10:38 +02:00
Dimitry Kolyshev
944e0d7a4b home: http client dns cache 2023-11-20 15:10:38 +02:00
219 changed files with 2441 additions and 4272 deletions

View File

@@ -1,7 +1,7 @@
'name': 'build'
'env':
'GO_VERSION': '1.20.12'
'GO_VERSION': '1.20.11'
'NODE_VERSION': '16'
'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint'
'env':
'GO_VERSION': '1.20.12'
'GO_VERSION': '1.20.11'
'on':
'push':

View File

@@ -14,128 +14,20 @@ and this project adheres to
<!--
## [v0.108.0] - TBA
## [v0.107.44] - 2023-12-20 (APPROX.)
## [v0.107.42] - 2023-12-06 (APPROX.)
See also the [v0.107.44 GitHub milestone][ms-v0.107.44].
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
[ms-v0.107.44]: https://github.com/AdguardTeam/AdGuardHome/milestone/79?closed=1
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
NOTE: Add new changes BELOW THIS COMMENT.
-->
### Added
- Etc timezones to the timezone list ([#6568]).
- The schema version of the configuration file to the output of running
`AdGuardHome` (or `AdGuardHome.exe) with `-v --version` command-line options
([#6545]).
- Ability to disable plain-DNS serving via UI if an encrypted protocol is
already used ([#1660]).
### Changed
- The bootstrapped upstream addresses now updated according to the TTL of the
bootstrap DNS response ([#6321]).
- Logging level of timeout errors is now `error` instead of `debug` ([#6574]).
- The field `"upstream_mode"` in `POST /control/dns_config` and
`GET /control/dns_info` HTTP APIs now accepts `load_balance` value. Check
`openapi/CHANGELOG.md` for more details.
#### Configuration changes
In this release, the schema version has changed from 27 to 28.
- The new property `clients.persistent.*.uid`, which is unique identifier of the
persistent client.
- The properties `dns.all_servers` and `dns.fastest_addr` were removed, their
values migrated to newly added field `dns.upstream_mode` that describes the
logic through which upstreams will be used. See also a [Wiki
page][wiki-config].
```yaml
# BEFORE:
'dns':
# …
'all_servers': true
'fastest_addr': true
# AFTER:
'dns':
# …
'upstream_mode': 'parallel'
```
To rollback this change, remove the new field `upstream_mode`, set back
`dns.all_servers` and `dns.fastest_addr` properties in `dns` section, and
change the `schema_version` back to `27`.
### Fixed
- Panic on using `--no-etc-hosts` flag ([#6644]).
- Schedule display in the client settings after creating or updating.
- Zero value in `querylog.size_memory` disables logging ([#6570]).
- Non-anonymized IP addresses on the dashboard ([#6584]).
- Maximum cache TTL requirement when editing minimum cache TTL in the Web UI
([#6409]).
- Load balancing algorithm stuck on a single server ([#6480]).
- Statistics for 7 days displayed as 168 hours on the dashboard.
- Pre-filling the Edit static lease window with data ([#6534]).
- Names defined in the `/etc/hosts` for a single address family wrongly
considered undefined for another family ([#6541]).
- Omitted CNAME records in safe search results, which can cause YouTube to not
work on iOS ([#6352]).
[#6321]: https://github.com/AdguardTeam/AdGuardHome/issues/6321
[#6352]: https://github.com/AdguardTeam/AdGuardHome/issues/6352
[#6409]: https://github.com/AdguardTeam/AdGuardHome/issues/6409
[#6480]: https://github.com/AdguardTeam/AdGuardHome/issues/6480
[#6534]: https://github.com/AdguardTeam/AdGuardHome/issues/6534
[#6541]: https://github.com/AdguardTeam/AdGuardHome/issues/6541
[#6545]: https://github.com/AdguardTeam/AdGuardHome/issues/6545
[#6568]: https://github.com/AdguardTeam/AdGuardHome/issues/6568
[#6570]: https://github.com/AdguardTeam/AdGuardHome/issues/6570
[#6574]: https://github.com/AdguardTeam/AdGuardHome/issues/6574
[#6584]: https://github.com/AdguardTeam/AdGuardHome/issues/6584
[#6644]: https://github.com/AdguardTeam/AdGuardHome/issues/6644
[wiki-config]: https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
-->
## [v0.107.43] - 2023-12-11
See also the [v0.107.43 GitHub milestone][ms-v0.107.43].
### Fixed
- Incorrect handling of IPv4-in-IPv6 addresses when binding to an unspecified
address on some machines ([#6510]).
[#6510]: https://github.com/AdguardTeam/AdGuardHome/issues/6510
[ms-v0.107.43]: https://github.com/AdguardTeam/AdGuardHome/milestone/78?closed=1
## [v0.107.42] - 2023-12-07
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
### Security
- Go version has been updated to prevent the possibility of exploiting the
CVE-2023-39326, CVE-2023-45283, and CVE-2023-45285 Go vulnerabilities fixed in
[Go 1.20.12][go-1.20.12].
### Added
- Ability to set client's custom DNS cache ([#6263]).
- Ability to set client's custom DNS cache ([#6362], [dnsproxy#169]).
- Ability to disable plain-DNS serving through configuration file if an
encrypted protocol is already enabled ([#1660]).
encrypted protocol is already used ([#1660]).
- Ability to specify rate limiting settings in the Web UI ([#6369]).
### Changed
@@ -157,13 +49,16 @@ See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
[#1660]: https://github.com/AdguardTeam/AdGuardHome/issues/1660
[#5759]: https://github.com/AdguardTeam/AdGuardHome/issues/5759
[#6263]: https://github.com/AdguardTeam/AdGuardHome/issues/6263
[#6362]: https://github.com/AdguardTeam/AdGuardHome/issues/6362
[#6369]: https://github.com/AdguardTeam/AdGuardHome/issues/6369
[#6402]: https://github.com/AdguardTeam/AdGuardHome/issues/6402
[#6420]: https://github.com/AdguardTeam/AdGuardHome/issues/6420
[go-1.20.12]: https://groups.google.com/g/golang-announce/c/iLGK3x6yuNo/m/z6MJ-eB0AQAJ
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
[dnsproxy#169] https://github.com/AdguardTeam/dnsproxy/issues/169
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
-->
@@ -2750,13 +2645,11 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
<!--
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.44...HEAD
[v0.107.44]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.43...v0.107.44
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.42...HEAD
[v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...v0.107.42
-->
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.43...HEAD
[v0.107.43]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.42...v0.107.43
[v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...v0.107.42
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.41...HEAD
[v0.107.41]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.40...v0.107.41
[v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.39...v0.107.40
[v0.107.39]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.38...v0.107.39

View File

@@ -276,15 +276,6 @@ Open your terminal and execute these commands:
git clone https://github.com/AdguardTeam/AdGuardHome
cd AdGuardHome
make
```
#### <a href="#building-node" id="building-node" name="building-node">Building with Node.js 17 and later</a>
In order to build AdGuard Home with Node.js 17 and later, specify
`--openssl-legacy-provider` option.
```sh
export NODE_OPTIONS=--openssl-legacy-provider
```
**NOTE:** The non-standard `-j` flag is currently not supported, so building
@@ -418,7 +409,6 @@ There are three options how you can install an unstable version:
```sh
curl -s -S -L https://raw.githubusercontent.com/AdguardTeam/AdGuardHome/master/scripts/install.sh | sh -s -- -c edge
```
[wiki-platf]: https://github.com/AdguardTeam/AdGuardHome/wiki/Platforms
@@ -473,6 +463,10 @@ bug or implementing the feature.
[@kongfl888](https://github.com/kongfl888) (originally by
[@rufengsuixing](https://github.com/rufengsuixing)).
* [Prometheus exporter for AdGuard
Home](https://github.com/ebrianne/adguard-exporter) by
[@ebrianne](https://github.com/ebrianne).
* [Terminal-based, real-time traffic monitoring and statistics for your AdGuard Home
instance](https://github.com/Lissy93/AdGuardian-Term) by
[@Lissy93](https://github.com/Lissy93)

View File

@@ -7,7 +7,7 @@
# Make sure to sync any changes with the branch overrides below.
'variables':
'channel': 'edge'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
'stages':
- 'Build frontend':
@@ -272,7 +272,7 @@
# need to build a few of these.
'variables':
'channel': 'beta'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
# release-vX.Y.Z branches are the branches from which the actual final
# release is built.
- '^release-v[0-9]+\.[0-9]+\.[0-9]+':
@@ -287,4 +287,4 @@
# are the ones that actually get released.
'variables':
'channel': 'release'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'

View File

@@ -10,7 +10,7 @@
# Make sure to sync any changes with the branch overrides below.
'variables':
'channel': 'edge'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
'snapcraftChannel': 'edge'
'stages':
@@ -191,7 +191,7 @@
# need to build a few of these.
'variables':
'channel': 'beta'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
'snapcraftChannel': 'beta'
# release-vX.Y.Z branches are the branches from which the actual final
# release is built.
@@ -207,5 +207,5 @@
# are the ones that actually get released.
'variables':
'channel': 'release'
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
'snapcraftChannel': 'candidate'

View File

@@ -5,7 +5,7 @@
'key': 'AHBRTSPECS'
'name': 'AdGuard Home - Build and run tests'
'variables':
'dockerGo': 'adguard/golang-ubuntu:7.6'
'dockerGo': 'adguard/golang-ubuntu:7.5'
'stages':
- 'Tests':

26
client/package-lock.json generated vendored
View File

@@ -11,7 +11,6 @@
"@nivo/line": "^0.64.0",
"axios": "^0.19.2",
"classnames": "^2.2.6",
"countries-and-timezones": "^3.6.0",
"date-fns": "^1.29.0",
"i18next": "^19.6.2",
"i18next-browser-languagedetector": "^4.2.0",
@@ -38,6 +37,7 @@
"redux-actions": "^2.6.5",
"redux-form": "^8.3.5",
"redux-thunk": "^2.3.0",
"timezones-list": "^3.0.2",
"url-polyfill": "^1.1.9"
},
"devDependencies": {
@@ -5596,15 +5596,6 @@
"node": ">=8"
}
},
"node_modules/countries-and-timezones": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.6.0.tgz",
"integrity": "sha512-8/nHBCs1eKeQ1jnsZVGdqrLYxS8nPcfJn8PnmxdJXWRLZdXsGFR8gnVhRjatGDBjqmPm7H+FtYpBYTPWd0Eiqg==",
"engines": {
"node": ">=8.x",
"npm": ">=5.x"
}
},
"node_modules/create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -18890,6 +18881,11 @@
"node": ">=0.6.0"
}
},
"node_modules/timezones-list": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/timezones-list/-/timezones-list-3.0.2.tgz",
"integrity": "sha512-I698hm6Jp/xxkwyTSOr39pZkYKETL8LDJeSIhjxXBfPUAHM5oZNuQ4o9UK3PSkDBOkjATecSOBb3pR1IkIBUsg=="
},
"node_modules/tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",
@@ -25272,11 +25268,6 @@
"yaml": "^1.7.2"
}
},
"countries-and-timezones": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/countries-and-timezones/-/countries-and-timezones-3.6.0.tgz",
"integrity": "sha512-8/nHBCs1eKeQ1jnsZVGdqrLYxS8nPcfJn8PnmxdJXWRLZdXsGFR8gnVhRjatGDBjqmPm7H+FtYpBYTPWd0Eiqg=="
},
"create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@@ -35683,6 +35674,11 @@
"setimmediate": "^1.0.4"
}
},
"timezones-list": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/timezones-list/-/timezones-list-3.0.2.tgz",
"integrity": "sha512-I698hm6Jp/xxkwyTSOr39pZkYKETL8LDJeSIhjxXBfPUAHM5oZNuQ4o9UK3PSkDBOkjATecSOBb3pR1IkIBUsg=="
},
"tiny-invariant": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz",

2
client/package.json vendored
View File

@@ -16,7 +16,6 @@
"@nivo/line": "^0.64.0",
"axios": "^0.19.2",
"classnames": "^2.2.6",
"countries-and-timezones": "^3.6.0",
"date-fns": "^1.29.0",
"i18next": "^19.6.2",
"i18next-browser-languagedetector": "^4.2.0",
@@ -43,6 +42,7 @@
"redux-actions": "^2.6.5",
"redux-form": "^8.3.5",
"redux-thunk": "^2.3.0",
"timezones-list": "^3.0.2",
"url-polyfill": "^1.1.9"
},
"devDependencies": {

View File

@@ -1,7 +1,6 @@
{
"client_settings": "Налады кліентаў",
"example_upstream_reserved": "upstream <0>для канкрэтных даменаў</0>;",
"example_multiple_upstreams_reserved": "некалькі DNS-сервераў <0>для канкрэтных даменаў</0>;",
"example_upstream_comment": "каментар.",
"upstream_parallel": "Ужыць адначасныя запыты да ўсіх сервераў для паскарэння апрацоўкі запыту",
"parallel_requests": "Паралельныя запыты",
@@ -144,8 +143,6 @@
"enforced_save_search": "Ужыты бяспечны пошук",
"number_of_dns_query_to_safe_search": "Колькасць запытаў DNS для пошукавых сістэм, для якіх быў ужыты Бяспечны пошук",
"average_processing_time": "Сярэдні час апрацоўкі запыту",
"average_upstream_response_time": "Сярэдні час водгуку upstream-сервера",
"response_time": "Час водгуку",
"average_processing_time_hint": "Сярэдні час для апрацоўкі запыту DNS у мілісекундах",
"block_domain_use_filters_and_hosts": "Блакаваць дамены з выкарыстаннем фільтраў і файлаў хастоў",
"filters_block_toggle_hint": "Вы можаце наладзіць правілы блакавання ў «<a>Фільтрах</a>».",
@@ -310,15 +307,6 @@
"edns_use_custom_ip": "Выкарыстоўваць указаны IP для DNS",
"edns_use_custom_ip_desc": "Дазволіць выкарыстоўваць уласны IP для DNS",
"rate_limit_desc": "Абмежаванне на колькасць запытаў у секунду для кожнага кліента (0 — неабмежавана)",
"rate_limit_subnet_len_ipv4": "Даўжыня прэфікса падсеткі для адрасоў IPv4",
"rate_limit_subnet_len_ipv4_desc": "Даўжыня прэфікса падсеткі для адрасоў IPv4, якія выкарыстоўваюцца для абмежавання хуткасці. Значэнне па змаўчанні 24",
"rate_limit_subnet_len_ipv4_error": "Даўжыня прэфікса падсеткі IPv4 павінна быць ад 0 да 32",
"rate_limit_subnet_len_ipv6": "Даўжыня прэфікса падсеткі для адрасоў IPv6",
"rate_limit_subnet_len_ipv6_desc": "Даўжыня прэфікса падсеткі для адрасоў IPv6, якія выкарыстоўваюцца для абмежавання хуткасці. Значэнне па змаўчанні 56",
"rate_limit_subnet_len_ipv6_error": "Даўжыня прэфікса падсеткі IPv6 павінна быць ад 0 да 128",
"form_enter_rate_limit_subnet_len": "Увядзіце даўжыню прэфікса падсеткі для абмежавання хуткасці",
"rate_limit_whitelist": "Белы спіс з абмежаваннем хуткасці",
"rate_limit_whitelist_desc": "IP-адрасы выключаны з абмежавання хуткасці",
"rate_limit_whitelist_placeholder": "Увядзіце па адным адрасе на радок",
"blocking_ipv4_desc": "IP-адрас, што вяртаецца пры блакаванню A-запыту",
"blocking_ipv6_desc": "IP-адрас, што вяртаецца пры блакаванню AAAA-запыту",
@@ -734,8 +722,5 @@
"wednesday_short": "Ср.",
"thursday_short": "Чц.",
"friday_short": "Пт.",
"saturday_short": "Сб.",
"upstream_dns_cache_configuration": "Канфігурацыя кэша upstream DNS-сервераў",
"enable_upstream_dns_cache": "Ўключыць кэшаванне для карыстацкай канфігурацыі upstream-сервераў гэтага кліента",
"dns_cache_size": "Памер кэша DNS, у байтах"
"saturday_short": "Сб."
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Středa",
"thursday_short": "Čtvrtek",
"friday_short": "Pátek",
"saturday_short": "Sobota",
"upstream_dns_cache_configuration": "Konfigurace mezipaměti odchozího DNS",
"enable_upstream_dns_cache": "Povolit ukládání do mezipaměti DNS pro vlastní konfiguraci odchozího připojení tohoto klienta",
"dns_cache_size": "Velikost mezipaměti DNS v bajtech"
"saturday_short": "Sobota"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Ons",
"thursday_short": "Tors",
"friday_short": "Fre",
"saturday_short": "Lør",
"upstream_dns_cache_configuration": "Upstream DNS-cacheopsætning",
"enable_upstream_dns_cache": "Aktivér DNS-cachelagring for denne klients tilpassede upstream-opsætning",
"dns_cache_size": "DNS-cachestørrelse i bytes"
"saturday_short": "Lør"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Mi",
"thursday_short": "Do",
"friday_short": "Fr",
"saturday_short": "Sa",
"upstream_dns_cache_configuration": "Konfiguration des Upstream-DNS-Cache",
"enable_upstream_dns_cache": "Caching für die benutzerdefinierte Upstream-Server-Konfiguration dieses Clients aktivieren",
"dns_cache_size": "Größe des DNS-Cache, in Bytes"
"saturday_short": "Sa"
}

View File

@@ -423,9 +423,6 @@
"encryption_hostnames": "Hostnames",
"encryption_reset": "Are you sure you want to reset encryption settings?",
"encryption_warning": "Warning",
"encryption_plain_dns_enable": "Enable plain DNS",
"encryption_plain_dns_desc": "Plain DNS is enabled by default. You can disable it to force all devices to use encrypted DNS. To do this, you must enable at least one encrypted DNS protocol",
"encryption_plain_dns_error": "To disable plain DNS, enable at least one encrypted DNS protocol",
"topline_expiring_certificate": "Your SSL certificate is about to expire. Update <0>Encryption settings</0>.",
"topline_expired_certificate": "Your SSL certificate is expired. Update <0>Encryption settings</0>.",
"form_error_port_range": "Enter port number in the range of 80-65535",

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Mié.",
"thursday_short": "Jue.",
"friday_short": "Vie.",
"saturday_short": "Sáb.",
"upstream_dns_cache_configuration": "Configuración de la caché DNS upstream",
"enable_upstream_dns_cache": "Habilitar el almacenamiento en caché de DNS para la configuración personalizada de este cliente",
"dns_cache_size": "Tamaño de la caché DNS, en bytes"
"saturday_short": "Sáb."
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Ke",
"thursday_short": "To",
"friday_short": "Pe",
"saturday_short": "La",
"upstream_dns_cache_configuration": "Ylävirran DNS-välimuistin määritykset",
"enable_upstream_dns_cache": "Käytä DNS-välimuistia tämän päätelaitteen mukautetuissa ylävirtamäärityksissä",
"dns_cache_size": "DNS-välimuistin koko tavuina"
"saturday_short": "La"
}

View File

@@ -310,15 +310,6 @@
"edns_use_custom_ip": "Utiliser une IP personnalisée pour EDNS",
"edns_use_custom_ip_desc": "Autoriser l'utilisation d'une adresse IP personnalisée pour EDNS",
"rate_limit_desc": "Le nombre de requêtes par seconde quun seul client est autorisé à faire. Le réglage 0 fait illimité.",
"rate_limit_subnet_len_ipv4": "Longueur du préfixe de sous-réseau pour les adresses IPv4",
"rate_limit_subnet_len_ipv4_desc": "Longueur du préfixe de sous-réseau pour les adresses IPv4 utilisé pour la limitation de vitesse. La valeur par défaut est 24",
"rate_limit_subnet_len_ipv4_error": "La longueur du préfixe du sous-réseau IPv4 doit être entre 0 et 32",
"rate_limit_subnet_len_ipv6": "Longueur du préfixe de sous-réseau pour les adresses IPv6",
"rate_limit_subnet_len_ipv6_desc": "Longueur du préfixe de sous-réseau pour les adresses IPv6 utilisé pour la limitation de débit. La valeur par défaut est 56",
"rate_limit_subnet_len_ipv6_error": "La longueur du préfixe du sous-réseau IPv6 doit être entre 0 et 128",
"form_enter_rate_limit_subnet_len": "Saisissez la longueur du préfixe de sous-réseau pour la limitation de débit",
"rate_limit_whitelist": "Liste d'autorisation de limitation de débit",
"rate_limit_whitelist_desc": "Adresses IP exclues de la limitation du débit",
"rate_limit_whitelist_placeholder": "Saisissez une adresse IP par ligne",
"blocking_ipv4_desc": "Adresse IP à renvoyer pour une demande A bloquée",
"blocking_ipv6_desc": "Adresse IP à renvoyer pour une demande AAAA bloquée",
@@ -734,8 +725,5 @@
"wednesday_short": "Mer.",
"thursday_short": "Jeu.",
"friday_short": "Ven.",
"saturday_short": "Sam.",
"upstream_dns_cache_configuration": "Configuration du cache DNS en amont",
"enable_upstream_dns_cache": "Activer la mise en cache pour la configuration personnalisée du serveur en amont de ce client",
"dns_cache_size": "Taille du cache DNS, en bytes"
"saturday_short": "Sam."
}

View File

@@ -310,15 +310,6 @@
"edns_use_custom_ip": "Koristi prilagođeni IP za EDNS",
"edns_use_custom_ip_desc": "Dopusti korištenje prilagođenog IP-a za EDNS",
"rate_limit_desc": "Broj zahtjeva u sekundi koji su dopušteni po jednom klijentu. Postavljanje na 0 znači neograničeno.",
"rate_limit_subnet_len_ipv4": "Duljina prefiksa podmreže za IPv4 adrese",
"rate_limit_subnet_len_ipv4_desc": "Duljina prefiksa podmreže za IPv4 adrese koje se koriste za ograničavanje brzine. Zadana vrijednost je 24",
"rate_limit_subnet_len_ipv4_error": "Dužina IPv4 prefiksa podmreže trebala bi biti između 0 i 32",
"rate_limit_subnet_len_ipv6": "Duljina prefiksa podmreže za IPv6 adrese",
"rate_limit_subnet_len_ipv6_desc": "Duljina prefiksa podmreže za IPv6 adrese koje se koriste za ograničavanje brzine. Zadana vrijednost je 56",
"rate_limit_subnet_len_ipv6_error": "Dužina IPv6 prefiksa podmreže trebala bi biti između 0 i 128",
"form_enter_rate_limit_subnet_len": "Unesite duljinu prefiksa podmreže za ograničenje brzine",
"rate_limit_whitelist": "Popis dopuštenih za ograničavanje brzine",
"rate_limit_whitelist_desc": "IP adrese isključene iz ograničenja brzine",
"rate_limit_whitelist_placeholder": "Unesite jednu adresu poslužitelja po retku",
"blocking_ipv4_desc": "Povratna IP adresa za blokirane A zahtjeve",
"blocking_ipv6_desc": "Povratna IP adresa za blokirane AAAA zahtjeve",
@@ -734,8 +725,5 @@
"wednesday_short": "Sri",
"thursday_short": "Čet",
"friday_short": "Pet",
"saturday_short": "Sub",
"upstream_dns_cache_configuration": "Konfiguracija predmemoriranja upstream DNS poslužitelja",
"enable_upstream_dns_cache": "Uključite keširanje za korisničku konfiguraciju upstream servera ovog klijenta",
"dns_cache_size": "Veličina DNS predmemorije, u bajtovima"
"saturday_short": "Sub"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Szer",
"thursday_short": "Csüt",
"friday_short": "Pén",
"saturday_short": "Szom",
"upstream_dns_cache_configuration": "Upstream DNS gyorsítótár konfigurációja",
"enable_upstream_dns_cache": "A DNS gyorsítótárazásának engedélyezése az ügyfél egyéni upstream konfigurációjához",
"dns_cache_size": "DNS gyorsítótár mérete, bájtokban"
"saturday_short": "Szom"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Rab",
"thursday_short": "Kam",
"friday_short": "Jum",
"saturday_short": "Sab",
"upstream_dns_cache_configuration": "Konfigurasi cache DNS upstream",
"enable_upstream_dns_cache": "Aktifkan cache DNS untuk konfigurasi upstream kustom klien ini",
"dns_cache_size": "Ukuran cache DNS, dalam byte"
"saturday_short": "Sab"
}

View File

@@ -310,15 +310,6 @@
"edns_use_custom_ip": "Usa IP personalizzato per EDNS",
"edns_use_custom_ip_desc": "Consentire l'uso di un IP personalizzato per EDNS",
"rate_limit_desc": "Il numero di richieste al secondo consentite da un singolo client. Impostare questo valore a 0 rimuove le limitazioni.",
"rate_limit_subnet_len_ipv4": "Lunghezza prefisso di sottorete per indirizzi IPv4",
"rate_limit_subnet_len_ipv4_desc": "Lunghezza prefisso sottorete per indirizzi IPv4 usati per la limitazione della velocità. Valore predefinito 24",
"rate_limit_subnet_len_ipv4_error": "La lunghezza del prefisso di sottorete IPv4 deve essere compresa tra 0 e 32",
"rate_limit_subnet_len_ipv6": "Lunghezza prefisso di sottorete per indirizzi IPv6",
"rate_limit_subnet_len_ipv6_desc": "Lunghezza prefisso di sottorete per indirizzi IPv6 usati per la limitazione della velocità. Valore predefinito 56",
"rate_limit_subnet_len_ipv6_error": "La lunghezza del prefisso di sottorete IPv6 deve essere compresa tra 0 e 128",
"form_enter_rate_limit_subnet_len": "Inserisci lunghezza prefisso di sottorete per limitazione velocità",
"rate_limit_whitelist": "Lista consentita per limitazione velocità",
"rate_limit_whitelist_desc": "Indirizzi IP esclusi dalla limitazione della velocità",
"rate_limit_whitelist_placeholder": "Inserisci un indirizzo IP per riga",
"blocking_ipv4_desc": "Indirizzo IP per una richiesta DNS IPv4 bloccata",
"blocking_ipv6_desc": "Indirizzo IP restituito per una richiesta DNS IPv6 bloccata",
@@ -734,8 +725,5 @@
"wednesday_short": "Mer",
"thursday_short": "Gio",
"friday_short": "Ven",
"saturday_short": "Sab",
"upstream_dns_cache_configuration": "Configurazione cache DNS upstream",
"enable_upstream_dns_cache": "Abilita cache DNS per la configurazione upstream personalizzata del client",
"dns_cache_size": "Dimensioni cache DNS (in byte)"
"saturday_short": "Sab"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "水",
"thursday_short": "木",
"friday_short": "金",
"saturday_short": "土",
"upstream_dns_cache_configuration": "Upstream DNS cache configurationアップストリームDNSキャッシュの構成",
"enable_upstream_dns_cache": "このクライアントのカスタムアップストリーム構成に対してDNSキャッシュを有効にする",
"dns_cache_size": "DNSキャッシュサイズバイト単位"
"saturday_short": "土"
}

View File

@@ -310,15 +310,6 @@
"edns_use_custom_ip": "EDNS에 사용자 지정 IP 사용",
"edns_use_custom_ip_desc": "EDNS에 사용자 지정 IP 사용하도록 허용합니다.",
"rate_limit_desc": "단일 클라이언트에서 허용 가능한 초 당 요청 생성 숫자 (0: 무제한)",
"rate_limit_subnet_len_ipv4": "IPv4 주소의 서브넷 접두사 길이",
"rate_limit_subnet_len_ipv4_desc": "속도 제한에 사용되는 IPv4 주소의 서브넷 접두사 길이입니다. 기본값은 24입니다.",
"rate_limit_subnet_len_ipv4_error": "IPv4 서브넷 접두사 길이는 0에서 32 사이여야 합니다.",
"rate_limit_subnet_len_ipv6": "IPv6 주소의 서브넷 접두사 길이",
"rate_limit_subnet_len_ipv6_desc": "속도 제한에 사용되는 IPv6 주소의 서브넷 접두사 길이입니다. 기본값은 56입니다.",
"rate_limit_subnet_len_ipv6_error": "IPv6 서브넷 접두사 길이는 0에서 128 사이여야 합니다.",
"form_enter_rate_limit_subnet_len": "속도 제한을 위한 서브넷 접두사 길이를 입력하세요",
"rate_limit_whitelist": "속도 제한 허용 목록",
"rate_limit_whitelist_desc": "속도 제한에서 제외되는 IP 주소",
"rate_limit_whitelist_placeholder": "한 줄에 하나씩 IP 주소를 입력하세요.",
"blocking_ipv4_desc": "차단된 A 요청에 대해서 반환할 IP 주소",
"blocking_ipv6_desc": "차단된 AAAA 요청에 대해서 반환할 IP 주소",
@@ -734,8 +725,5 @@
"wednesday_short": "수",
"thursday_short": "목",
"friday_short": "금",
"saturday_short": "토",
"upstream_dns_cache_configuration": "업스트림 DNS 캐시 설정",
"enable_upstream_dns_cache": "이 클라이언트의 사용자 지정 업스트림 설정에서 DNS 캐싱 사용",
"dns_cache_size": "DNS 캐시 크기(바이트)"
"saturday_short": "토"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "wo",
"thursday_short": "do",
"friday_short": "vr",
"saturday_short": "za",
"upstream_dns_cache_configuration": "Upstream DNS-cacheconfiguratie",
"enable_upstream_dns_cache": "DNS-caching inschakelen voor de aangepaste upstream-configuratie van deze client",
"dns_cache_size": "DNS-cachegrootte, in bytes"
"saturday_short": "za"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Śro",
"thursday_short": "Czw",
"friday_short": "Pt",
"saturday_short": "Sob",
"upstream_dns_cache_configuration": "Konfiguracja pamięci podręcznej upstream serwerów DNS",
"enable_upstream_dns_cache": "Włącz pamięć podręczną dla niestandardowej konfiguracji serwera upstream tego klienta",
"dns_cache_size": "Rozmiar pamięci podręcznej DNS, w bajtach"
"saturday_short": "Sob"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Quar",
"thursday_short": "Qui",
"friday_short": "Sex",
"saturday_short": "Sab",
"upstream_dns_cache_configuration": "Configuração do cache de DNS upstream",
"enable_upstream_dns_cache": "Ativar o armazenamento em cache do DNS para a configuração de upstream personalizada deste cliente",
"dns_cache_size": "Tamanho do cache do DNS, em bytes"
"saturday_short": "Sab"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Quarta",
"thursday_short": "Quinta",
"friday_short": "Sexta",
"saturday_short": "Sábado",
"upstream_dns_cache_configuration": "Configuração da cache do DNS upstream",
"enable_upstream_dns_cache": "Ativar o armazenamento em cache do DNS para a configuração de upstream personalizada deste cliente",
"dns_cache_size": "Tamanho da cache DNS, em bytes"
"saturday_short": "Sábado"
}

View File

@@ -310,15 +310,6 @@
"edns_use_custom_ip": "Utilizați IP personalizat pentru EDNS",
"edns_use_custom_ip_desc": "Permiteți utilizarea IP-ului personalizat pentru EDNS",
"rate_limit_desc": "Numărul de interogări pe secundă permise pe client. Setarea la 0 înseamnă că nu există limită.",
"rate_limit_subnet_len_ipv4": "Lungimea prefixului de subrețea pentru adrese IPv4",
"rate_limit_subnet_len_ipv4_desc": "Lungimea prefixului de subrețea pentru adresele IPv4 utilizate pentru limitarea ratei. Valoarea implicită este 24",
"rate_limit_subnet_len_ipv4_error": "Lungimea prefixului de subrețea IPv4 ar trebui să fie între 0 și 32",
"rate_limit_subnet_len_ipv6": "Lungimea prefixului de subrețea pentru adrese IPv6",
"rate_limit_subnet_len_ipv6_desc": "Lungimea prefixului de subrețea pentru adresele IPv6 utilizate pentru limitarea ratei. Valoarea implicită este 56",
"rate_limit_subnet_len_ipv6_error": "Lungimea prefixului de subrețea IPv6 ar trebui să fie între 0 și 128",
"form_enter_rate_limit_subnet_len": "Introduceți lungimea prefixului de subrețea pentru limitarea ratei",
"rate_limit_whitelist": "Lista permisă pentru limitarea ratei",
"rate_limit_whitelist_desc": "Adresele IP excluse de la limitarea ratei",
"rate_limit_whitelist_placeholder": "Introduceți o adresă IP per linie",
"blocking_ipv4_desc": "Adresa IP de returnat pentru o cerere A de blocare",
"blocking_ipv6_desc": "Adresa IP de returnat pentru o cerere AAAA de blocare",
@@ -734,8 +725,5 @@
"wednesday_short": "mi",
"thursday_short": "jo",
"friday_short": "vi",
"saturday_short": "sa",
"upstream_dns_cache_configuration": "Configurarea cache-ului DNS în amonte",
"enable_upstream_dns_cache": "Activați memoria cache DNS pentru configurația personalizată în amonte a acestui client",
"dns_cache_size": "Dimensiunea cache-ului DNS, în octeți"
"saturday_short": "sa"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Ср",
"thursday_short": "Чт",
"friday_short": "Пт",
"saturday_short": "Сб",
"upstream_dns_cache_configuration": "Конфигурация кеша upstream DNS-серверов",
"enable_upstream_dns_cache": "Включить кеширование для пользовательской конфигурации upstream-серверов этого клиента",
"dns_cache_size": "Размер DNS-кеша в байтах"
"saturday_short": "Сб"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Str",
"thursday_short": "Štr",
"friday_short": "Pia",
"saturday_short": "Sob",
"upstream_dns_cache_configuration": "Konfigurácia cache pamäte DNS pre upstream",
"enable_upstream_dns_cache": "Zapnúť ukladanie DNS do cache pamäte pre vlastnú konfiguráciu odosielania tohto klienta",
"dns_cache_size": "Veľkosť cache pamäte DNS v bajtoch"
"saturday_short": "Sob"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Sre",
"thursday_short": "Čet",
"friday_short": "Pet",
"saturday_short": "Sob",
"upstream_dns_cache_configuration": "Nastavitve predpomnilnika gorvodnega DNS",
"enable_upstream_dns_cache": "Omogoči predpomnjenje nastavitev gorvodnega DNS po meri tega odjemalca",
"dns_cache_size": "Velikost predpomnilnika DNS, v bajtih"
"saturday_short": "Sob"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Sre",
"thursday_short": "Čet",
"friday_short": "Pet",
"saturday_short": "Sub",
"upstream_dns_cache_configuration": "Konfiguracija keša upstream DNS servera",
"enable_upstream_dns_cache": "Uključite keširanje za korisničku konfiguraciju upstream servera ovog klijenta",
"dns_cache_size": "Veličina DNS keša, u bajtovima"
"saturday_short": "Sub"
}

View File

@@ -310,14 +310,6 @@
"edns_use_custom_ip": "Använd anpassad IP för EDNS",
"edns_use_custom_ip_desc": "Tillåt att använda anpassad IP för EDNS",
"rate_limit_desc": "Antalet förfrågningar per sekund som tillåts per klient. Att sätta den till 0 innebär ingen gräns.",
"rate_limit_subnet_len_ipv4": "Prefixlängd för subnät för IPv4-adresser",
"rate_limit_subnet_len_ipv4_desc": "Subnätprefixlängd för IPv4-adresser som används för hastighetsbegränsning. Standard är 24",
"rate_limit_subnet_len_ipv4_error": "IPv4-subnätets prefixlängd ska vara mellan 0 och 32",
"rate_limit_subnet_len_ipv6": "Prefixlängd för subnät för IPv6-adresser",
"rate_limit_subnet_len_ipv6_desc": "Subnätprefixlängd för IPv6-adresser som används för hastighetsbegränsning. Standard är 56",
"rate_limit_subnet_len_ipv6_error": "IPv6-subnätets prefixlängd ska vara mellan 0 och 128",
"form_enter_rate_limit_subnet_len": "Ange subnätprefixlängd för hastighetsbegränsning",
"rate_limit_whitelist_desc": "IP-adresser uteslutna från hastighetsbegränsning",
"rate_limit_whitelist_placeholder": "Ange en IP-adress per rad",
"blocking_ipv4_desc": "IP adress som ska returneras för en blockerad A förfrågan",
"blocking_ipv6_desc": "IP adress som ska returneras för en blockerad AAAA förfrågan",
@@ -733,8 +725,5 @@
"wednesday_short": "Ons",
"thursday_short": "Tor",
"friday_short": "Fre",
"saturday_short": "Lör",
"upstream_dns_cache_configuration": "Konfiguration av uppströms DNS-cache",
"enable_upstream_dns_cache": "Aktivera DNS-cachelagring för den här klientens anpassade uppströmskonfiguration",
"dns_cache_size": "DNS-cachestorlek, i byte"
"saturday_short": "Lör"
}

View File

@@ -322,7 +322,7 @@
"rate_limit_whitelist_placeholder": "Her satıra bir IP adresi girin",
"blocking_ipv4_desc": "Engellenen bir A isteği için geri döndürülecek IP adresi",
"blocking_ipv6_desc": "Engellenen bir AAAA isteği için geri döndürülecek IP adresi",
"blocking_mode_default": "Varsayılan: Reklam engelleme stili kuralı tarafından engellendiğinde sıfır IP adresiyle (A için 0.0.0.0; :: AAAA için) yanıt verin; /etc/hosts-tarzı kural tarafından engellendiğinde, kuralda belirtilen IP adresiyle yanıt verin",
"blocking_mode_default": "Varsayılan: Reklam engelleme tarzı kural tarafından engellendiğinde sıfır IP adresiyle (A için 0.0.0.0; :: AAAA için) yanıt verin; /etc/hosts-tarzı kural tarafından engellendiğinde, kuralda belirtilen IP adresiyle yanıt verin",
"blocking_mode_refused": "REFUSED: REFUSED koduyla yanıt verin",
"blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN koduyla yanıt verin",
"blocking_mode_null_ip": "Boş IP: Sıfır IP adresiyle yanıt verin (A için 0.0.0.0; :: AAAA için)",
@@ -734,8 +734,5 @@
"wednesday_short": "Çar",
"thursday_short": "Per",
"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",
"dns_cache_size": "DNS önbellek boyutu, bayt cinsinden"
"saturday_short": "Cmt"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "СР",
"thursday_short": "ЧТ",
"friday_short": "ПТ",
"saturday_short": "СБ",
"upstream_dns_cache_configuration": "Конфігурація кешу upstream DNS-серверів",
"enable_upstream_dns_cache": "Увімкнути кешування для користувацької конфігурації upstream-серверів цього клієнта",
"dns_cache_size": "Розмір кешу DNS, у байтах"
"saturday_short": "СБ"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "Thứ 4",
"thursday_short": "Thứ 5",
"friday_short": "Thứ 6",
"saturday_short": "Thứ 7",
"upstream_dns_cache_configuration": "Cấu hình bộ nhớ đệm upstream của các máy chủ DNS",
"enable_upstream_dns_cache": "Bật bộ nhớ cache cho cấu hình ngược dòng của máy chủ upstream của khách hàng này",
"dns_cache_size": "Kích thước bộ nhớ cache DNS, tính bằng byte"
"saturday_short": "Thứ 7"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "周三",
"thursday_short": "周四",
"friday_short": "周五",
"saturday_short": "周六",
"upstream_dns_cache_configuration": "上游 DNS 缓存配置",
"enable_upstream_dns_cache": "为该客户端的自定义上游配置启用 DNS 缓存",
"dns_cache_size": "DNS 缓存大小,单位:字节"
"saturday_short": "周六"
}

View File

@@ -734,8 +734,5 @@
"wednesday_short": "週三",
"thursday_short": "週四",
"friday_short": "週五",
"saturday_short": "週六",
"upstream_dns_cache_configuration": "上游 DNS 快取設定",
"enable_upstream_dns_cache": "啟用本用戶端自訂上游配置的 DNS 快取",
"dns_cache_size": "DNS 快取大小,單位:位元"
"saturday_short": "週六"
}

View File

@@ -1,5 +1,5 @@
import React from 'react';
import ct from 'countries-and-timezones';
import timezones from 'timezones-list';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
@@ -15,8 +15,6 @@ export const Timezone = ({
setTimezone(event.target.value);
};
const timezones = ct.getAllTimezones();
return (
<div className="schedule__timezone">
<label className="form__label form__label--with-desc mb-2">
@@ -32,9 +30,9 @@ export const Timezone = ({
{t('schedule_timezone')}
</option>
{/* TODO: get timezones from backend method when the method is ready */}
{Object.keys(timezones).map((zone) => (
<option key={zone} value={zone}>
{zone} (GMT{timezones[zone].utcOffsetStr})
{timezones.map((zone) => (
<option key={zone.name} value={zone.tzCode}>
{zone.label}
</option>
))}
</select>

View File

@@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useState, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import PropTypes from 'prop-types';
import cn from 'classnames';
@@ -21,7 +21,10 @@ export const ScheduleForm = ({
const onModalOpen = () => setModalOpen(true);
const onModalClose = () => setModalOpen(false);
const filteredScheduleKeys = schedule ? Object.keys(schedule).filter((v) => v !== 'time_zone') : [];
const filteredScheduleKeys = useMemo(() => (
schedule ? Object.keys(schedule).filter((v) => v !== 'time_zone') : []
), [schedule]);
const scheduleMap = new Map();
filteredScheduleKeys.forEach((day) => scheduleMap.set(day, schedule[day]));

View File

@@ -162,7 +162,7 @@ let Form = (props) => {
const [activeTabLabel, setActiveTabLabel] = useState('settings');
const handleScheduleSubmit = (values) => {
change('blocked_services_schedule', { ...values });
change('blocked_services_schedule', values);
};
const tabs = {

View File

@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import ReactTable from 'react-table';
import { Trans, withTranslation } from 'react-i18next';
import { LEASES_TABLE_DEFAULT_PAGE_SIZE, MODAL_TYPE } from '../../../helpers/constants';
import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../helpers/constants';
import { sortIp } from '../../../helpers/helpers';
import { toggleLeaseModal } from '../../../actions';
@@ -18,10 +18,7 @@ class Leases extends Component {
convertToStatic = (data) => () => {
const { dispatch } = this.props;
dispatch(toggleLeaseModal({
type: MODAL_TYPE.ADD_LEASE,
config: data,
}));
dispatch(toggleLeaseModal(data));
}
makeStatic = ({ row }) => {

View File

@@ -41,7 +41,7 @@ const Form = ({
cache_ttl_max, cache_ttl_min,
} = useSelector((state) => state.form[FORM_NAME.CACHE].values, shallowEqual);
const minExceedsMax = cache_ttl_min > 0 && cache_ttl_max > 0 && cache_ttl_min > cache_ttl_max;
const minExceedsMax = cache_ttl_min > cache_ttl_max;
const handleClearCache = () => {
if (window.confirm(t('confirm_dns_cache_clear'))) {

View File

@@ -12,7 +12,7 @@ import {
toNumber,
} from '../../../helpers/form';
import {
validateServerName, validateIsSafePort, validatePort, validatePortQuic, validatePortTLS, validatePlainDns,
validateServerName, validateIsSafePort, validatePort, validatePortQuic, validatePortTLS,
} from '../../../helpers/validators';
import i18n from '../../../i18n';
import KeyStatus from './KeyStatus';
@@ -47,7 +47,6 @@ const clearFields = (change, setTlsConfig, validateTlsConfig, t) => {
force_https: false,
enabled: false,
private_key_saved: false,
serve_plain_dns: true,
};
// eslint-disable-next-line no-alert
if (window.confirm(t('encryption_reset'))) {
@@ -84,7 +83,6 @@ let Form = (props) => {
handleSubmit,
handleChange,
isEnabled,
servePlainDns,
certificateChain,
privateKey,
certificatePath,
@@ -111,24 +109,21 @@ let Form = (props) => {
privateKeySaved,
} = props;
const isSavingDisabled = () => {
const processing = submitting || processingConfig || processingValidate;
const isSavingDisabled = invalid
|| submitting
|| processingConfig
|| processingValidate
|| !valid_key
|| !valid_cert
|| !valid_pair;
if (servePlainDns && !isEnabled) {
return invalid || processing;
}
return invalid || processing || !valid_key || !valid_cert || !valid_pair;
};
const isDisabled = isSavingDisabled();
const isWarning = valid_key && valid_cert && valid_pair;
return (
<form onSubmit={handleSubmit}>
<div className="row">
<div className="col-12">
<div className="form__group form__group--settings mb-3">
<div className="form__group form__group--settings">
<Field
name="enabled"
type="checkbox"
@@ -140,19 +135,6 @@ let Form = (props) => {
<div className="form__desc">
<Trans>encryption_enable_desc</Trans>
</div>
<div className="form__group mb-3 mt-5">
<Field
name="serve_plain_dns"
type="checkbox"
component={CheckboxField}
placeholder={t('encryption_plain_dns_enable')}
onChange={handleChange}
validate={validatePlainDns}
/>
</div>
<div className="form__desc">
<Trans>encryption_plain_dns_desc</Trans>
</div>
<hr />
</div>
<div className="col-12">
@@ -245,16 +227,16 @@ let Form = (props) => {
<Trans>encryption_doq</Trans>
</label>
<Field
id="port_dns_over_quic"
name="port_dns_over_quic"
component={renderInputField}
type="number"
className="form-control"
placeholder={t('encryption_doq')}
validate={[validatePortQuic]}
normalize={toNumber}
onChange={handleChange}
disabled={!isEnabled}
id="port_dns_over_quic"
name="port_dns_over_quic"
component={renderInputField}
type="number"
className="form-control"
placeholder={t('encryption_doq')}
validate={[validatePortQuic]}
normalize={toNumber}
onChange={handleChange}
disabled={!isEnabled}
/>
<div className="form__desc">
<Trans>encryption_doq_desc</Trans>
@@ -430,8 +412,8 @@ let Form = (props) => {
<div className="btn-list mt-2">
<button
type="submit"
disabled={isDisabled}
className="btn btn-success btn-standart"
disabled={isSavingDisabled}
>
<Trans>save_config</Trans>
</button>
@@ -452,7 +434,6 @@ Form.propTypes = {
handleSubmit: PropTypes.func.isRequired,
handleChange: PropTypes.func,
isEnabled: PropTypes.bool.isRequired,
servePlainDns: PropTypes.bool.isRequired,
certificateChain: PropTypes.string.isRequired,
privateKey: PropTypes.string.isRequired,
certificatePath: PropTypes.string.isRequired,
@@ -486,7 +467,6 @@ const selector = formValueSelector(FORM_NAME.ENCRYPTION);
Form = connect((state) => {
const isEnabled = selector(state, 'enabled');
const servePlainDns = selector(state, 'serve_plain_dns');
const certificateChain = selector(state, 'certificate_chain');
const privateKey = selector(state, 'private_key');
const certificatePath = selector(state, 'certificate_path');
@@ -496,7 +476,6 @@ Form = connect((state) => {
const privateKeySaved = selector(state, 'private_key_saved');
return {
isEnabled,
servePlainDns,
certificateChain,
privateKey,
certificatePath,

View File

@@ -25,8 +25,7 @@ class Encryption extends Component {
handleFormChange = debounce((values) => {
const submitValues = this.getSubmitValues(values);
if (submitValues.enabled || submitValues.serve_plain_dns) {
if (submitValues.enabled) {
this.props.validateTlsConfig(submitValues);
}
}, DEBOUNCE_TIMEOUT);
@@ -86,7 +85,6 @@ class Encryption extends Component {
certificate_path,
private_key_path,
private_key_saved,
serve_plain_dns,
} = encryption;
const initialValues = this.getInitialValues({
@@ -101,7 +99,6 @@ class Encryption extends Component {
certificate_path,
private_key_path,
private_key_saved,
serve_plain_dns,
});
return (

View File

@@ -181,7 +181,6 @@ export const MODAL_TYPE = {
ADD_REWRITE: 'ADD_REWRITE',
EDIT_REWRITE: 'EDIT_REWRITE',
EDIT_LEASE: 'EDIT_LEASE',
ADD_LEASE: 'ADD_LEASE',
};
export const CLIENT_ID = {
@@ -436,7 +435,7 @@ export const SCHEME_TO_PROTOCOL_MAP = {
export const DNS_REQUEST_OPTIONS = {
PARALLEL: 'parallel',
FASTEST_ADDR: 'fastest_addr',
LOAD_BALANCING: 'load_balance',
LOAD_BALANCING: '',
};
export const DHCP_FORM_NAMES = {

View File

@@ -142,11 +142,11 @@ export default {
"homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"
},
"awavenue_ads_rule": {
"name": "AWAvenue Ads Rule",
"adway_default_blocklist": {
"name": "AdAway Default Blocklist",
"categoryId": "general",
"homepage": "https://awavenue.top/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_53.txt"
"homepage": "https://github.com/AdAway/adaway.github.io/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt"
},
"curben_phishing_filter": {
"name": "Phishing URL Blocklist (PhishTank and OpenPhish)",
@@ -190,12 +190,6 @@ export default {
"homepage": "https://github.com/hagezi/dns-blocklists#piracy",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_46.txt"
},
"hagezi_dyndns_blocklist": {
"name": "HaGeZi's DynDNS Blocklist",
"categoryId": "security",
"homepage": "https://github.com/hagezi/dns-blocklists",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_54.txt"
},
"hagezi_encrypted_dns_vpn_tor_proxy_bypass": {
"name": "HaGeZi's Encrypted DNS/VPN/TOR/Proxy Bypass",
"categoryId": "security",

View File

@@ -180,7 +180,7 @@ export const CheckboxField = ({
{!disabled
&& touched
&& error
&& <div className="form__message form__message--error mt-1"><Trans>{error}</Trans></div>}
&& <span className="form__message form__message--error"><Trans>{error}</Trans></span>}
</>;
CheckboxField.propTypes = {

View File

@@ -1,5 +1,5 @@
{
"timeUpdated": "2024-01-22T00:10:10.554Z",
"timeUpdated": "2023-11-10T12:55:56.663Z",
"categories": {
"0": "audio_video_player",
"1": "comments",
@@ -640,8 +640,7 @@
"name": "AdChina",
"categoryId": 4,
"url": "http://www.adchina.com/",
"companyId": null,
"source": "AdGuard"
"companyId": "alibaba"
},
"adcito": {
"name": "Adcito",
@@ -1322,13 +1321,6 @@
"companyId": "adobe",
"source": "AdGuard"
},
"adobe_experience_league": {
"name": "Adobe Experience League",
"categoryId": 6,
"url": "https://experienceleague.adobe.com/",
"companyId": "adobe",
"source": "AdGuard"
},
"adobe_login": {
"name": "Adobe Login",
"categoryId": 2,
@@ -2289,29 +2281,27 @@
"name": "Alibaba",
"categoryId": 8,
"url": "http://www.alibaba.com/",
"companyId": "softbank",
"source": "AdGuard"
"companyId": "alibaba"
},
"alibaba_cloud": {
"name": "Alibaba Cloud",
"categoryId": 10,
"url": "https://www.alibabacloud.com/",
"companyId": "softbank",
"companyId": "alibaba",
"source": "AdGuard"
},
"alibaba_ucbrowser": {
"name": "UC Browser",
"categoryId": 8,
"url": "https://ucweb.com/",
"companyId": "softbank",
"companyId": "alibaba",
"source": "AdGuard"
},
"alipay.com": {
"name": "Alipay",
"categoryId": 2,
"url": "https://global.alipay.com/",
"companyId": "softbank",
"source": "AdGuard"
"url": "https://www.alipay.com/",
"companyId": "alibaba"
},
"alivechat": {
"name": "AliveChat",
@@ -3777,11 +3767,10 @@
"companyId": "branica"
},
"braze": {
"name": "Braze, Inc.",
"name": "Braze",
"categoryId": 6,
"url": "https://www.braze.com/",
"companyId": "braze",
"source": "AdGuard"
"companyId": "braze_inc"
},
"brealtime": {
"name": "EMX Digital",
@@ -10758,10 +10747,9 @@
},
"localytics": {
"name": "Localytics",
"categoryId": 101,
"url": "https://uplandsoftware.com/localytics/",
"companyId": "upland",
"source": "AdGuard"
"categoryId": 6,
"url": "http://www.localytics.com/",
"companyId": "localytics"
},
"lockerdome": {
"name": "LockerDome",
@@ -12546,7 +12534,7 @@
"name": "Network Time Protocol",
"categoryId": 5,
"url": "https://ntp.org/",
"companyId": "network_time_foundation",
"companyId": "ntppool",
"source": "AdGuard"
},
"nttcom_online_marketing_solutions": {
@@ -15614,11 +15602,10 @@
"companyId": "sharecompany"
},
"sharepoint": {
"name": "SharePoint",
"categoryId": 8,
"url": "https://www.microsoft.com/microsoft-365/sharepoint/collaboration",
"companyId": "microsoft",
"source": "AdGuard"
"name": "Microsoft SharePoint",
"categoryId": 2,
"url": "https://products.office.com/en-us/sharepoint/sharepoint-online-collaboration-software",
"companyId": "microsoft"
},
"sharethis": {
"name": "ShareThis",
@@ -17075,8 +17062,7 @@
"name": "Taobao",
"categoryId": 4,
"url": "https://world.taobao.com/",
"companyId": "softbank",
"source": "AdGuard"
"companyId": "alibaba"
},
"tapad": {
"name": "Tapad",
@@ -20445,7 +20431,6 @@
"nedstat.com": "adobe_experience_cloud",
"omtrdc.net": "adobe_experience_cloud",
"sitestat.com": "adobe_experience_cloud",
"adobedc.net": "adobe_experience_league",
"adobelogin.com": "adobe_login",
"adobetag.com": "adobe_tagmanager",
"typekit.com": "adobe_typekit",
@@ -21061,7 +21046,6 @@
"brandwire.tv": "brandwire.tv",
"branica.com": "branica",
"appboycdn.com": "braze",
"braze.com": "braze",
"brealtime.com": "brealtime",
"bridgetrack.com": "bridgetrack",
"brightcove.com": "brightcove",
@@ -22960,7 +22944,6 @@
"loadercdn.com": "loadercdn.com",
"loadsource.org": "loadsource.org",
"web.localytics.com": "localytics",
"localytics.com": "localytics",
"cdn2.lockerdome.com": "lockerdome",
"addtoany.com": "lockerz_share",
"pixel.loganmedia.mobi": "logan_media",
@@ -23157,11 +23140,8 @@
"s-microsoft.com": "microsoft",
"trouter.io": "microsoft",
"windows.net": "microsoft",
"aka.ms": "microsoft",
"microsoftazuread-sso.com": "microsoft",
"bingapis.com": "microsoft",
"msauth.net": "microsoft",
"msauthimages.net": "microsoft",
"msftauth.net": "microsoft",
"msftstatic.com": "microsoft",
"msidentity.com": "microsoft",
@@ -23252,14 +23232,10 @@
"mrpdata.net": "mrpdata",
"mrskincash.com": "mrskincash",
"a-msedge.net": "msedge",
"b-msedge.net": "msedge",
"e-msedge.net": "msedge",
"k-msedge.net": "msedge",
"l-msedge.net": "msedge",
"s-msedge.net": "msedge",
"spo-msedge.net": "msedge",
"t-msedge.net": "msedge",
"wac-msedge.net": "msedge",
"msn.com": "msn",
"s-msn.com": "msn",
"musculahq.appspot.com": "muscula",
@@ -23525,10 +23501,8 @@
"outbrain.com": "outbrain",
"outbrainimg.com": "outbrain",
"live.com": "outlook",
"cloud.microsoft": "outlook",
"hotmail.com": "outlook",
"outlook.com": "outlook",
"svc.ms": "outlook",
"overheat.it": "overheat.it",
"oewabox.at": "owa",
"owneriq.net": "owneriq",
@@ -23796,7 +23770,6 @@
"rcsmediagroup.it": "rcs.it",
"d335luupugsy2.cloudfront.net": "rd_station",
"rea-group.com": "rea_group",
"reagroupdata.com.au": "rea_group",
"reastatic.net": "rea_group",
"d12ulf131zb0yj.cloudfront.net": "reachforce",
"reachforce.com": "reachforce",
@@ -24116,8 +24089,6 @@
"quintrics.nl": "sharecompany",
"sharecompany.nl": "sharecompany",
"sharepointonline.com": "sharepoint",
"onmicrosoft.com": "sharepoint",
"sharepoint.com": "sharepoint",
"sharethis.com": "sharethis",
"shareth.ru": "sharethrough",
"sharethrough.com": "sharethrough",

View File

@@ -389,18 +389,3 @@ export const validateIPv6Subnet = (value) => {
}
return undefined;
};
/**
* @returns {undefined|string}
* @param value
* @param allValues
*/
export const validatePlainDns = (value, allValues) => {
const { enabled } = allValues;
if (!enabled && !value) {
return 'encryption_plain_dns_error';
}
return undefined;
};

View File

@@ -128,8 +128,7 @@ const dhcp = handleActions(
const newState = {
...state,
isModalOpen: !state.isModalOpen,
modalType: payload?.type || '',
leaseModalConfig: payload?.config,
leaseModalConfig: payload,
};
return newState;
},

View File

@@ -1,7 +1,7 @@
import { handleActions } from 'redux-actions';
import * as actions from '../actions/dnsConfig';
import { ALL_INTERFACES_IP, BLOCKING_MODES, DNS_REQUEST_OPTIONS } from '../helpers/constants';
import { ALL_INTERFACES_IP, BLOCKING_MODES } from '../helpers/constants';
const DEFAULT_BLOCKING_IPV4 = ALL_INTERFACES_IP;
const DEFAULT_BLOCKING_IPV6 = '::';
@@ -15,7 +15,6 @@ const dnsConfig = handleActions(
blocking_ipv4,
blocking_ipv6,
upstream_dns,
upstream_mode,
fallback_dns,
bootstrap_dns,
local_ptr_upstreams,
@@ -34,7 +33,6 @@ const dnsConfig = handleActions(
local_ptr_upstreams: (local_ptr_upstreams && local_ptr_upstreams.join('\n')) || '',
ratelimit_whitelist: (ratelimit_whitelist && ratelimit_whitelist.join('\n')) || '',
processingGetConfig: false,
upstream_mode: upstream_mode === '' ? DNS_REQUEST_OPTIONS.LOAD_BALANCING : upstream_mode,
};
},

View File

@@ -62,7 +62,6 @@ const encryption = handleActions({
processingConfig: false,
processingValidate: false,
enabled: false,
serve_plain_dns: false,
dns_names: null,
force_https: false,
issuer: '',

38
go.mod
View File

@@ -3,13 +3,12 @@ module github.com/AdguardTeam/AdGuardHome
go 1.20
require (
github.com/AdguardTeam/dnsproxy v0.63.1
github.com/AdguardTeam/golibs v0.19.0
github.com/AdguardTeam/dnsproxy v0.59.1
github.com/AdguardTeam/golibs v0.17.2
github.com/AdguardTeam/urlfilter v0.17.3
github.com/NYTimes/gziphandler v1.1.1
github.com/ameshkov/dnscrypt/v2 v2.2.7
github.com/bluele/gcache v0.0.2
github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500
github.com/digineo/go-ipset/v2 v2.2.1
github.com/dimfeld/httptreemux/v5 v5.5.0
github.com/fsnotify/fsnotify v1.7.0
@@ -17,8 +16,8 @@ require (
github.com/google/go-cmp v0.6.0
github.com/google/gopacket v1.1.19
github.com/google/renameio/v2 v2.0.0
github.com/google/uuid v1.5.0
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
github.com/google/uuid v1.4.0
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c
github.com/josharian/native v1.1.1-0.20230202152459-5c7d0dd6ab86
github.com/kardianos/service v1.2.2
github.com/mdlayher/ethernet v0.0.0-20220221185849-529eae5b6118
@@ -27,18 +26,18 @@ require (
// TODO(a.garipov): This package is deprecated; find a new one or use our
// own code for that. Perhaps, use gopacket.
github.com/mdlayher/raw v0.1.0
github.com/miekg/dns v1.1.58
github.com/miekg/dns v1.1.56
github.com/quic-go/quic-go v0.40.0
github.com/stretchr/testify v1.8.4
github.com/ti-mo/netfilter v0.5.1
go.etcd.io/bbolt v1.3.8
golang.org/x/crypto v0.18.0
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
golang.org/x/net v0.20.0
golang.org/x/sys v0.16.0
golang.org/x/crypto v0.15.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/net v0.18.0
golang.org/x/sys v0.14.0
gopkg.in/natefinch/lumberjack.v2 v2.2.1
gopkg.in/yaml.v3 v3.0.1
howett.net/plist v1.0.1
howett.net/plist v1.0.0
)
require (
@@ -48,21 +47,20 @@ require (
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815 // indirect
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a // indirect
// TODO(a.garipov): Upgrade to v0.5.0 once we switch to Go 1.21+.
github.com/mdlayher/socket v0.5.0 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/mdlayher/socket v0.4.1 // indirect
github.com/onsi/ginkgo/v2 v2.13.1 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e // indirect
go.uber.org/mock v0.4.0 // indirect
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 // indirect
go.uber.org/mock v0.3.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/sync v0.6.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.17.0 // indirect
gonum.org/v1/gonum v0.14.0 // indirect
golang.org/x/tools v0.15.0 // indirect
)

78
go.sum
View File

@@ -1,7 +1,7 @@
github.com/AdguardTeam/dnsproxy v0.63.1 h1:CilxSuLYcuYpbPCGB7w41UUqWRMu3dvj4c9TvkIrpBg=
github.com/AdguardTeam/dnsproxy v0.63.1/go.mod h1:dRRAFOjrq4QYM92jGs4lt4BoY0Dm3EY3HkaleoM2Feo=
github.com/AdguardTeam/golibs v0.19.0 h1:y/x+Xn3pDg1ZfQ+QEZapPJqaeVYUIMp/EODMtVhn7PM=
github.com/AdguardTeam/golibs v0.19.0/go.mod h1:3WunclLLfrVAq7fYQRhd6f168FHOEMssnipVXCxDL/w=
github.com/AdguardTeam/dnsproxy v0.59.1 h1:G/6T32EuPF0rhRkACkLFwD0pajI9351a1LACpuA2UcE=
github.com/AdguardTeam/dnsproxy v0.59.1/go.mod h1:ZvkbM71HwpilgkCnTubDiR4Ba6x5Qvnhy2iasMWaTDM=
github.com/AdguardTeam/golibs v0.17.2 h1:vg6wHMjUKscnyPGRvxS5kAt7Uw4YxcJiITZliZ476W8=
github.com/AdguardTeam/golibs v0.17.2/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
github.com/AdguardTeam/urlfilter v0.17.3 h1:fg/ObbnO0Cv6aw0tW6N/ETDMhhNvmcUUOZ7HlmKC3rw=
github.com/AdguardTeam/urlfilter v0.17.3/go.mod h1:Jru7jFfeH2CoDf150uDs+rRYcZBzHHBz05r9REyDKyE=
github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I=
@@ -18,8 +18,6 @@ github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0 h1:0b2vaepXIfMsG+
github.com/beefsack/go-rate v0.0.0-20220214233405-116f4ca011a0/go.mod h1:6YNgTHLutezwnBvyneBbwvB8C82y3dcoOj5EQJIdGXA=
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/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=
@@ -43,16 +41,16 @@ 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/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-20240117000934-35fc243c5815 h1:WzfWbQz/Ze8v6l++GGbGNFZnUShVpP/0xffCPLL+ax8=
github.com/google/pprof v0.0.0-20240117000934-35fc243c5815/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5XqmmYsTLzJp/TO9Lhy39gkverk=
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
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/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hugelgupf/socketpair v0.0.0-20190730060125-05d35a94e714 h1:/jC7qQFrv8CrSJVmaolDVOxTfS9kc36uB6H40kdbQq8=
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2 h1:9K06NfxkBh25x56yVhWWlKFE8YpicaSfHwoV8SFbueA=
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c h1:PgxFEySCI41sH0mB7/2XswdXbUykQsRUGod8Rn+NubM=
github.com/insomniacslk/dhcp v0.0.0-20231016090811-6a2c8fbdcc1c/go.mod h1:3A9PQ1cunSDF/1rbTq99Ts4pVnycWg+vlPkfeD2NLFI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
github.com/josharian/native v1.0.1-0.20221213033349-c1e37c09b531/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
@@ -73,19 +71,19 @@ github.com/mdlayher/packet v1.1.2/go.mod h1:GEu1+n9sG5VtiRE4SydOmX5GTwyyYlteZiFU
github.com/mdlayher/raw v0.1.0 h1:K4PFMVy+AFsp0Zdlrts7yNhxc/uXoPVHi9RzRvtZF2Y=
github.com/mdlayher/raw v0.1.0/go.mod h1:yXnxvs6c0XoF/aK52/H5PjsVHmWBCFfZUfoh/Y5s9Sg=
github.com/mdlayher/socket v0.2.1/go.mod h1:QLlNPkFR88mRUNQIzRBMfXxwKal8H7u1h3bL1CV+f0E=
github.com/mdlayher/socket v0.5.0 h1:ilICZmJcQz70vrWVes1MFera4jGiWNocSkykwwoy3XI=
github.com/mdlayher/socket v0.5.0/go.mod h1:WkcBFfvyG8QENs5+hfQPl1X6Jpd2yeLIYgrGFmJiJxI=
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY=
github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM=
github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8=
github.com/onsi/ginkgo/v2 v2.13.1 h1:LNGfMbR2OVGBfXjvRZIZ2YCTQdGKtPLvuI1rMCCj3OU=
github.com/onsi/ginkgo/v2 v2.13.1/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -111,19 +109,19 @@ github.com/ti-mo/netfilter v0.5.1 h1:cqamEd1c1zmpfpqvInLOro0Znq/RAfw2QL5wL2rAR/8
github.com/ti-mo/netfilter v0.5.1/go.mod h1:h9UPQ3ZrTZGBitay+LETMxZvNgWGK/efTUcqES2YiLw=
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e h1:BA9O3BmlTmpjbvajAwzWx4Wo2TRVdpPXZEeemGQcajw=
github.com/u-root/uio v0.0.0-20240118234441-a3c409a6018e/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63 h1:YcojQL98T/OO+rybuzn2+5KrD5dBwXIvYBvQ2cD3Avg=
github.com/u-root/uio v0.0.0-20230305220412-3e8cd9d6bf63/go.mod h1:eLL9Nub3yfAho7qB0MzZizFhTU2QkLeoVsWdHtDW264=
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
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.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
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.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
@@ -134,12 +132,12 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
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.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
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.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -151,8 +149,8 @@ golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/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.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
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=
@@ -160,12 +158,10 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
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=
gonum.org/v1/gonum v0.14.0 h1:2NiG67LD1tEH0D7kM+ps2V+fXmsAnpUeec7n8tcr4S0=
gonum.org/v1/gonum v0.14.0/go.mod h1:AoWeoz0becf9QMWtE8iWXNXc27fK4fNeHNf/oMejGfU=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
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=
@@ -175,5 +171,5 @@ gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=

View File

@@ -1,15 +1,23 @@
package aghalg
import (
"github.com/AdguardTeam/golibs/errors"
)
// RingBuffer is the implementation of ring buffer data structure.
type RingBuffer[T any] struct {
buf []T
cur uint
cur int
full bool
}
// NewRingBuffer initializes the new instance of ring buffer. size must be
// greater or equal to zero.
func NewRingBuffer[T any](size uint) (rb *RingBuffer[T]) {
func NewRingBuffer[T any](size int) (rb *RingBuffer[T]) {
if size < 0 {
panic(errors.Error("ring buffer: size must be greater or equal to zero"))
}
return &RingBuffer[T]{
buf: make([]T, size),
}
@@ -22,7 +30,7 @@ func (rb *RingBuffer[T]) Append(e T) {
}
rb.buf[rb.cur] = e
rb.cur = (rb.cur + 1) % uint(cap(rb.buf))
rb.cur = (rb.cur + 1) % cap(rb.buf)
if rb.cur == 0 {
rb.full = true
}
@@ -79,12 +87,12 @@ func (rb *RingBuffer[T]) splitCur() (before, after []T) {
}
// Len returns a length of the buffer.
func (rb *RingBuffer[T]) Len() (l uint) {
func (rb *RingBuffer[T]) Len() (l int) {
if !rb.full {
return rb.cur
}
return uint(cap(rb.buf))
return cap(rb.buf)
}
// Clear clears the buffer.

View File

@@ -9,13 +9,13 @@ import (
)
// elements is a helper function that returns n elements of the buffer.
func elements(b *aghalg.RingBuffer[int], n uint, reverse bool) (es []int) {
func elements(b *aghalg.RingBuffer[int], n int, reverse bool) (es []int) {
fn := b.Range
if reverse {
fn = b.ReverseRange
}
var i uint
i := 0
fn(func(e int) (cont bool) {
if i >= n {
return false
@@ -42,14 +42,19 @@ func TestNewRingBuffer(t *testing.T) {
assert.Zero(t, b.Len())
})
t.Run("negative_size", func(t *testing.T) {
assert.PanicsWithError(t, "ring buffer: size must be greater or equal to zero", func() {
aghalg.NewRingBuffer[int](-5)
})
})
t.Run("zero", func(t *testing.T) {
b := aghalg.NewRingBuffer[int](0)
for i := 0; i < 10; i++ {
b.Append(i)
bufLen := b.Len()
assert.EqualValues(t, 0, bufLen)
assert.Empty(t, elements(b, bufLen, false))
assert.Empty(t, elements(b, bufLen, true))
assert.Equal(t, 0, b.Len())
assert.Empty(t, elements(b, b.Len(), false))
assert.Empty(t, elements(b, b.Len(), true))
}
})
@@ -57,10 +62,9 @@ func TestNewRingBuffer(t *testing.T) {
b := aghalg.NewRingBuffer[int](1)
for i := 0; i < 10; i++ {
b.Append(i)
bufLen := b.Len()
assert.EqualValues(t, 1, bufLen)
assert.Equal(t, []int{i}, elements(b, bufLen, false))
assert.Equal(t, []int{i}, elements(b, bufLen, true))
assert.Equal(t, 1, b.Len())
assert.Equal(t, []int{i}, elements(b, b.Len(), false))
assert.Equal(t, []int{i}, elements(b, b.Len(), true))
}
})
}
@@ -74,7 +78,7 @@ func TestRingBuffer_Range(t *testing.T) {
name string
want []int
count int
length uint
length int
}{{
name: "three",
count: 3,
@@ -159,11 +163,11 @@ func TestRingBuffer_Range_increment(t *testing.T) {
for i, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
b.Append(i)
bufLen := b.Len()
assert.Equal(t, tc.want, elements(b, bufLen, false))
assert.Equal(t, tc.want, elements(b, b.Len(), false))
slices.Reverse(tc.want)
assert.Equal(t, tc.want, elements(b, bufLen, true))
assert.Equal(t, tc.want, elements(b, b.Len(), true))
})
}
}

View File

@@ -0,0 +1,33 @@
// Package aghchan contains channel utilities.
package aghchan
import (
"fmt"
"time"
)
// Receive returns an error if it cannot receive a value form c before timeout
// runs out.
func Receive[T any](c <-chan T, timeout time.Duration) (v T, ok bool, err error) {
var zero T
timeoutCh := time.After(timeout)
select {
case <-timeoutCh:
// TODO(a.garipov): Consider implementing [errors.Aser] for
// os.ErrTimeout.
return zero, false, fmt.Errorf("did not receive after %s", timeout)
case v, ok = <-c:
return v, ok, nil
}
}
// MustReceive panics if it cannot receive a value form c before timeout runs
// out.
func MustReceive[T any](c <-chan T, timeout time.Duration) (v T, ok bool) {
v, ok, err := Receive(c, timeout)
if err != nil {
panic(err)
}
return v, ok
}

View File

@@ -1,23 +1,65 @@
package aghnet
import (
"context"
"fmt"
"io"
"io/fs"
"net/netip"
"path"
"strings"
"sync/atomic"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/dnsproxy/upstream"
"github.com/AdguardTeam/golibs/errors"
"github.com/AdguardTeam/golibs/hostsfile"
"github.com/AdguardTeam/golibs/log"
"golang.org/x/exp/maps"
"golang.org/x/exp/slices"
)
// DefaultHostsPaths returns the slice of paths default for the operating system
// to files and directories which are containing the hosts database. The result
// is intended to be used within fs.FS so the initial slash is omitted.
func DefaultHostsPaths() (paths []string) {
return defaultHostsPaths()
}
// MatchAddr returns the records for the IP address.
func (hc *HostsContainer) MatchAddr(ip netip.Addr) (recs []*hostsfile.Record) {
cur := hc.current.Load()
if cur == nil {
return nil
}
return cur.addrs[ip]
}
// MatchName returns the records for the hostname.
func (hc *HostsContainer) MatchName(name string) (recs []*hostsfile.Record) {
cur := hc.current.Load()
if cur != nil {
recs = cur.names[name]
}
return recs
}
// hostsContainerPrefix is a prefix for logging and wrapping errors in
// HostsContainer's methods.
const hostsContainerPrefix = "hosts container"
// Hosts is a map of IP addresses to the records, as it primarily stored in the
// [HostsContainer]. It should not be accessed for writing since it may be read
// concurrently, users should clone it before modifying.
//
// The order of records for each address is preserved from original files, but
// the order of the addresses, being a map key, is not.
//
// TODO(e.burkov): Probably, this should be a sorted slice of records.
type Hosts map[netip.Addr][]*hostsfile.Record
// HostsContainer stores the relevant hosts database provided by the OS and
// processes both A/AAAA and PTR DNS requests for those.
type HostsContainer struct {
@@ -25,10 +67,10 @@ type HostsContainer struct {
done chan struct{}
// updates is the channel for receiving updated hosts.
updates chan *hostsfile.DefaultStorage
updates chan Hosts
// current is the last set of hosts parsed.
current atomic.Pointer[hostsfile.DefaultStorage]
current atomic.Pointer[hostsIndex]
// fsys is the working file system to read hosts files from.
fsys fs.FS
@@ -69,7 +111,7 @@ func NewHostsContainer(
hc = &HostsContainer{
done: make(chan struct{}, 1),
updates: make(chan *hostsfile.DefaultStorage, 1),
updates: make(chan Hosts, 1),
fsys: fsys,
watcher: w,
patterns: patterns,
@@ -110,25 +152,11 @@ func (hc *HostsContainer) Close() (err error) {
return err
}
// Upd returns the channel into which the updates are sent. The updates
// themselves must not be modified.
func (hc *HostsContainer) Upd() (updates <-chan *hostsfile.DefaultStorage) {
// Upd returns the channel into which the updates are sent.
func (hc *HostsContainer) Upd() (updates <-chan Hosts) {
return hc.updates
}
// type check
var _ hostsfile.Storage = (*HostsContainer)(nil)
// ByAddr implements the [hostsfile.Storage] interface for *HostsContainer.
func (hc *HostsContainer) ByAddr(addr netip.Addr) (names []string) {
return hc.current.Load().ByAddr(addr)
}
// ByName implements the [hostsfile.Storage] interface for *HostsContainer.
func (hc *HostsContainer) ByName(name string) (addrs []netip.Addr) {
return hc.current.Load().ByName(name)
}
// pathsToPatterns converts paths into patterns compatible with fs.Glob.
func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error) {
for i, p := range paths {
@@ -139,7 +167,7 @@ func pathsToPatterns(fsys fs.FS, paths []string) (patterns []string, err error)
continue
}
// Don't put a filename here since it's already added by [fs.Stat].
// Don't put a filename here since it's already added by fs.Stat.
return nil, fmt.Errorf("path at index %d: %w", i, err)
}
@@ -181,7 +209,7 @@ func (hc *HostsContainer) handleEvents() {
}
// sendUpd tries to send the parsed data to the ch.
func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
func (hc *HostsContainer) sendUpd(recs Hosts) {
log.Debug("%s: sending upd", hostsContainerPrefix)
ch := hc.updates
@@ -198,6 +226,67 @@ func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
}
}
// hostsIndex is a [hostsfile.Set] to enumerate all the records.
type hostsIndex struct {
// addrs maps IP addresses to the records.
addrs Hosts
// names maps hostnames to the records.
names map[string][]*hostsfile.Record
}
// walk is a file walking function for hostsIndex.
func (idx *hostsIndex) walk(r io.Reader) (patterns []string, cont bool, err error) {
return nil, true, hostsfile.Parse(idx, r, nil)
}
// type check
var _ hostsfile.Set = (*hostsIndex)(nil)
// Add implements the [hostsfile.Set] interface for *hostsIndex.
func (idx *hostsIndex) Add(rec *hostsfile.Record) {
idx.addrs[rec.Addr] = append(idx.addrs[rec.Addr], rec)
for _, name := range rec.Names {
idx.names[name] = append(idx.names[name], rec)
}
}
// type check
var _ hostsfile.HandleSet = (*hostsIndex)(nil)
// HandleInvalid implements the [hostsfile.HandleSet] interface for *hostsIndex.
func (idx *hostsIndex) HandleInvalid(src string, _ []byte, err error) {
lineErr := &hostsfile.LineError{}
if !errors.As(err, &lineErr) {
// Must not happen if idx passed to [hostsfile.Parse].
return
} else if errors.Is(lineErr, hostsfile.ErrEmptyLine) {
// Ignore empty lines.
return
}
log.Info("%s: warning: parsing %q: %s", hostsContainerPrefix, src, lineErr)
}
// equalRecs is an equality function for [*hostsfile.Record].
func equalRecs(a, b *hostsfile.Record) (ok bool) {
return a.Addr == b.Addr && a.Source == b.Source && slices.Equal(a.Names, b.Names)
}
// equalRecSlices is an equality function for slices of [*hostsfile.Record].
func equalRecSlices(a, b []*hostsfile.Record) (ok bool) { return slices.EqualFunc(a, b, equalRecs) }
// Equal returns true if indexes are equal.
func (idx *hostsIndex) Equal(other *hostsIndex) (ok bool) {
if idx == nil {
return other == nil
} else if other == nil {
return false
}
return maps.EqualFunc(idx.addrs, other.addrs, equalRecSlices)
}
// refresh gets the data from specified files and propagates the updates if
// needed.
//
@@ -205,22 +294,63 @@ func (hc *HostsContainer) sendUpd(recs *hostsfile.DefaultStorage) {
func (hc *HostsContainer) refresh() (err error) {
log.Debug("%s: refreshing", hostsContainerPrefix)
// The error is always nil here since no readers passed.
strg, _ := hostsfile.NewDefaultStorage()
_, err = aghos.FileWalker(func(r io.Reader) (patterns []string, cont bool, err error) {
// Don't wrap the error since it's already informative enough as is.
return nil, true, hostsfile.Parse(strg, r, nil)
}).Walk(hc.fsys, hc.patterns...)
var addrLen, nameLen int
last := hc.current.Load()
if last != nil {
addrLen, nameLen = len(last.addrs), len(last.names)
}
idx := &hostsIndex{
addrs: make(Hosts, addrLen),
names: make(map[string][]*hostsfile.Record, nameLen),
}
_, err = aghos.FileWalker(idx.walk).Walk(hc.fsys, hc.patterns...)
if err != nil {
// Don't wrap the error since it's informative enough as is.
return err
}
// TODO(e.burkov): Serialize updates using [time.Time].
if !hc.current.Load().Equal(strg) {
hc.current.Store(strg)
hc.sendUpd(strg)
// TODO(e.burkov): Serialize updates using time.
if !last.Equal(idx) {
hc.current.Store(idx)
hc.sendUpd(idx.addrs)
}
return nil
}
// type check
var _ upstream.Resolver = (*HostsContainer)(nil)
// LookupNetIP implements the [upstream.Resolver] interface for *HostsContainer.
func (hc *HostsContainer) LookupNetIP(
ctx context.Context,
network string,
hostname string,
) (addrs []netip.Addr, err error) {
// TODO(e.burkov): Think of extracting this logic to a golibs function if
// needed anywhere else.
var isDesiredProto func(ip netip.Addr) (ok bool)
switch network {
case "ip4":
isDesiredProto = (netip.Addr).Is4
case "ip6":
isDesiredProto = (netip.Addr).Is6
case "ip":
isDesiredProto = func(ip netip.Addr) (ok bool) { return true }
default:
return nil, fmt.Errorf("unsupported network: %q", network)
}
idx := hc.current.Load()
recs := idx.names[strings.ToLower(hostname)]
addrs = make([]netip.Addr, 0, len(recs))
for _, rec := range recs {
if isDesiredProto(rec.Addr) {
addrs = append(addrs, rec.Addr)
}
}
return slices.Clip(addrs), nil
}

View File

@@ -0,0 +1,17 @@
//go:build linux
package aghnet
import (
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
)
func defaultHostsPaths() (paths []string) {
paths = []string{"etc/hosts"}
if aghos.IsOpenWrt() {
paths = append(paths, "tmp/hosts")
}
return paths
}

View File

@@ -0,0 +1,7 @@
//go:build !(windows || linux)
package aghnet
func defaultHostsPaths() (paths []string) {
return []string{"etc/hosts"}
}

View File

@@ -3,11 +3,13 @@ package aghnet_test
import (
"net/netip"
"path"
"path/filepath"
"sync/atomic"
"testing"
"testing/fstest"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/aghchan"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
"github.com/AdguardTeam/golibs/errors"
@@ -18,6 +20,139 @@ import (
"github.com/stretchr/testify/require"
)
// nl is a newline character.
const nl = "\n"
// Variables mirroring the etc_hosts file from testdata.
var (
addr1000 = netip.MustParseAddr("1.0.0.0")
addr1001 = netip.MustParseAddr("1.0.0.1")
addr1002 = netip.MustParseAddr("1.0.0.2")
addr1003 = netip.MustParseAddr("1.0.0.3")
addr1004 = netip.MustParseAddr("1.0.0.4")
addr1357 = netip.MustParseAddr("1.3.5.7")
addr4216 = netip.MustParseAddr("4.2.1.6")
addr7531 = netip.MustParseAddr("7.5.3.1")
addr0 = netip.MustParseAddr("::")
addr1 = netip.MustParseAddr("::1")
addr2 = netip.MustParseAddr("::2")
addr3 = netip.MustParseAddr("::3")
addr4 = netip.MustParseAddr("::4")
addr42 = netip.MustParseAddr("::42")
addr13 = netip.MustParseAddr("::13")
addr31 = netip.MustParseAddr("::31")
hostsSrc = "./" + filepath.Join("./testdata", "etc_hosts")
testHosts = map[netip.Addr][]*hostsfile.Record{
addr1000: {{
Addr: addr1000,
Source: hostsSrc,
Names: []string{"hello", "hello.world"},
}, {
Addr: addr1000,
Source: hostsSrc,
Names: []string{"hello.world.again"},
}, {
Addr: addr1000,
Source: hostsSrc,
Names: []string{"hello.world"},
}},
addr1001: {{
Addr: addr1001,
Source: hostsSrc,
Names: []string{"simplehost"},
}, {
Addr: addr1001,
Source: hostsSrc,
Names: []string{"simplehost"},
}},
addr1002: {{
Addr: addr1002,
Source: hostsSrc,
Names: []string{"a.whole", "lot.of", "aliases", "for.testing"},
}},
addr1003: {{
Addr: addr1003,
Source: hostsSrc,
Names: []string{"*"},
}},
addr1004: {{
Addr: addr1004,
Source: hostsSrc,
Names: []string{"*.com"},
}},
addr1357: {{
Addr: addr1357,
Source: hostsSrc,
Names: []string{"domain4", "domain4.alias"},
}},
addr7531: {{
Addr: addr7531,
Source: hostsSrc,
Names: []string{"domain4.alias", "domain4"},
}},
addr4216: {{
Addr: addr4216,
Source: hostsSrc,
Names: []string{"domain", "domain.alias"},
}},
addr0: {{
Addr: addr0,
Source: hostsSrc,
Names: []string{"hello", "hello.world"},
}, {
Addr: addr0,
Source: hostsSrc,
Names: []string{"hello.world.again"},
}, {
Addr: addr0,
Source: hostsSrc,
Names: []string{"hello.world"},
}},
addr1: {{
Addr: addr1,
Source: hostsSrc,
Names: []string{"simplehost"},
}, {
Addr: addr1,
Source: hostsSrc,
Names: []string{"simplehost"},
}},
addr2: {{
Addr: addr2,
Source: hostsSrc,
Names: []string{"a.whole", "lot.of", "aliases", "for.testing"},
}},
addr3: {{
Addr: addr3,
Source: hostsSrc,
Names: []string{"*"},
}},
addr4: {{
Addr: addr4,
Source: hostsSrc,
Names: []string{"*.com"},
}},
addr42: {{
Addr: addr42,
Source: hostsSrc,
Names: []string{"domain.alias", "domain"},
}},
addr13: {{
Addr: addr13,
Source: hostsSrc,
Names: []string{"domain6", "domain6.alias"},
}},
addr31: {{
Addr: addr31,
Source: hostsSrc,
Names: []string{"domain6.alias", "domain6"},
}},
}
)
func TestNewHostsContainer(t *testing.T) {
const dirname = "dir"
const filename = "file1"
@@ -132,21 +267,7 @@ func TestHostsContainer_refresh(t *testing.T) {
anotherIPStr := "1.2.3.4"
anotherIP := netip.MustParseAddr(anotherIPStr)
r1 := &hostsfile.Record{
Addr: ip,
Source: "file1",
Names: []string{"hostname"},
}
r2 := &hostsfile.Record{
Addr: anotherIP,
Source: "file2",
Names: []string{"alias"},
}
r1Data, _ := r1.MarshalText()
r2Data, _ := r2.MarshalText()
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: r1Data}}
testFS := fstest.MapFS{"dir/file1": &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}}
// event is a convenient alias for an empty struct{} to emit test events.
type event = struct{}
@@ -168,47 +289,172 @@ func TestHostsContainer_refresh(t *testing.T) {
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
strg, _ := hostsfile.NewDefaultStorage()
strg.Add(r1)
checkRefresh := func(t *testing.T, want aghnet.Hosts) {
t.Helper()
upd, ok := aghchan.MustReceive(hc.Upd(), 1*time.Second)
require.True(t, ok)
assert.Equal(t, want, upd)
}
t.Run("initial_refresh", func(t *testing.T) {
upd, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
require.True(t, ok)
assert.True(t, strg.Equal(upd))
checkRefresh(t, aghnet.Hosts{
ip: {{
Addr: ip,
Source: "file1",
Names: []string{"hostname"},
}},
})
})
strg.Add(r2)
t.Run("second_refresh", func(t *testing.T) {
testFS["dir/file2"] = &fstest.MapFile{Data: r2Data}
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(anotherIPStr + ` alias` + nl)}
eventsCh <- event{}
upd, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
require.True(t, ok)
assert.True(t, strg.Equal(upd))
checkRefresh(t, aghnet.Hosts{
ip: {{
Addr: ip,
Source: "file1",
Names: []string{"hostname"},
}},
anotherIP: {{
Addr: anotherIP,
Source: "file2",
Names: []string{"alias"},
}},
})
})
t.Run("double_refresh", func(t *testing.T) {
// Make a change once.
testFS["dir/file1"] = &fstest.MapFile{Data: []byte(ipStr + " alias\n")}
testFS["dir/file1"] = &fstest.MapFile{Data: []byte(ipStr + ` alias` + nl)}
eventsCh <- event{}
// Require the changes are written.
current, ok := testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
require.True(t, ok)
require.Eventually(t, func() bool {
ips := hc.MatchName("hostname")
require.Empty(t, current.ByName("hostname"))
return len(ips) == 0
}, 5*time.Second, time.Second/2)
// Make a change again.
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + " hostname\n")}
testFS["dir/file2"] = &fstest.MapFile{Data: []byte(ipStr + ` hostname` + nl)}
eventsCh <- event{}
// Require the changes are written.
current, ok = testutil.RequireReceive(t, hc.Upd(), 1*time.Second)
require.True(t, ok)
require.Eventually(t, func() bool {
ips := hc.MatchName("hostname")
require.NotEmpty(t, current.ByName("hostname"))
return len(ips) > 0
}, 5*time.Second, time.Second/2)
assert.Len(t, hc.Upd(), 1)
})
}
func TestHostsContainer_MatchName(t *testing.T) {
require.NoError(t, fstest.TestFS(testdata, "etc_hosts"))
stubWatcher := aghtest.FSWatcher{
OnEvents: func() (e <-chan struct{}) { return nil },
OnAdd: func(name string) (err error) { return nil },
OnClose: func() (err error) { return nil },
}
testCases := []struct {
req string
name string
want []*hostsfile.Record
}{{
req: "simplehost",
name: "simple",
want: append(testHosts[addr1001], testHosts[addr1]...),
}, {
req: "hello.world",
name: "hello_alias",
want: []*hostsfile.Record{
testHosts[addr1000][0],
testHosts[addr1000][2],
testHosts[addr0][0],
testHosts[addr0][2],
},
}, {
req: "hello.world.again",
name: "other_line_alias",
want: []*hostsfile.Record{
testHosts[addr1000][1],
testHosts[addr0][1],
},
}, {
req: "say.hello",
name: "hello_subdomain",
want: nil,
}, {
req: "say.hello.world",
name: "hello_alias_subdomain",
want: nil,
}, {
req: "for.testing",
name: "lots_of_aliases",
want: append(testHosts[addr1002], testHosts[addr2]...),
}, {
req: "nonexistent.example",
name: "non-existing",
want: nil,
}, {
req: "domain",
name: "issue_4216_4_6",
want: append(testHosts[addr4216], testHosts[addr42]...),
}, {
req: "domain4",
name: "issue_4216_4",
want: append(testHosts[addr1357], testHosts[addr7531]...),
}, {
req: "domain6",
name: "issue_4216_6",
want: append(testHosts[addr13], testHosts[addr31]...),
}}
hc, err := aghnet.NewHostsContainer(testdata, &stubWatcher, "etc_hosts")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
recs := hc.MatchName(tc.req)
assert.Equal(t, tc.want, recs)
})
}
}
func TestHostsContainer_MatchAddr(t *testing.T) {
require.NoError(t, fstest.TestFS(testdata, "etc_hosts"))
stubWatcher := aghtest.FSWatcher{
OnEvents: func() (e <-chan struct{}) { return nil },
OnAdd: func(name string) (err error) { return nil },
OnClose: func() (err error) { return nil },
}
hc, err := aghnet.NewHostsContainer(testdata, &stubWatcher, "etc_hosts")
require.NoError(t, err)
testutil.CleanupAndRequireSuccess(t, hc.Close)
testCases := []struct {
req netip.Addr
name string
want []*hostsfile.Record
}{{
req: netip.AddrFrom4([4]byte{1, 0, 0, 1}),
name: "reverse",
want: testHosts[addr1001],
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
recs := hc.MatchAddr(tc.req)
assert.Equal(t, tc.want, recs)
})
}
}

View File

@@ -0,0 +1,32 @@
//go:build windows
package aghnet
import (
"os"
"path"
"path/filepath"
"strings"
"github.com/AdguardTeam/golibs/log"
"golang.org/x/sys/windows"
)
func defaultHostsPaths() (paths []string) {
sysDir, err := windows.GetSystemDirectory()
if err != nil {
log.Error("aghnet: getting system directory: %s", err)
return []string{}
}
// Split all the elements of the path to join them afterwards. This is
// needed to make the Windows-specific path string returned by
// windows.GetSystemDirectory to be compatible with fs.FS.
pathElems := strings.Split(sysDir, string(os.PathSeparator))
if len(pathElems) > 0 && pathElems[0] == filepath.VolumeName(sysDir) {
pathElems = pathElems[1:]
}
return []string{path.Join(append(pathElems, "drivers/etc/hosts")...)}
}

View File

@@ -1,9 +1,11 @@
package aghnet_test
import (
"io/fs"
"net"
"net/netip"
"net/url"
"os"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
@@ -16,6 +18,9 @@ func TestMain(m *testing.M) {
testutil.DiscardLogOutput(m)
}
// testdata is the filesystem containing data for testing the package.
var testdata fs.FS = os.DirFS("./testdata")
func TestParseAddrPort(t *testing.T) {
const defaultPort = 1

38
internal/aghnet/testdata/etc_hosts vendored Normal file
View File

@@ -0,0 +1,38 @@
#
# Test /etc/hosts file
#
1.0.0.1 simplehost
1.0.0.0 hello hello.world
# See https://github.com/AdguardTeam/AdGuardHome/issues/3846.
1.0.0.2 a.whole lot.of aliases for.testing
# See https://github.com/AdguardTeam/AdGuardHome/issues/3946.
1.0.0.3 *
1.0.0.4 *.com
# See https://github.com/AdguardTeam/AdGuardHome/issues/4079.
1.0.0.0 hello.world.again
# Duplicates of a main host and an alias.
1.0.0.1 simplehost
1.0.0.0 hello.world
# Same for IPv6.
::1 simplehost
:: hello hello.world
::2 a.whole lot.of aliases for.testing
::3 *
::4 *.com
:: hello.world.again
::1 simplehost
:: hello.world
# See https://github.com/AdguardTeam/AdGuardHome/issues/4216.
4.2.1.6 domain domain.alias
::42 domain.alias domain
1.3.5.7 domain4 domain4.alias
7.5.3.1 domain4.alias domain4
::13 domain6 domain6.alias
::31 domain6.alias domain6

1
internal/aghnet/testdata/ifaces vendored Normal file
View File

@@ -0,0 +1 @@
iface sample_name inet static

View File

@@ -0,0 +1,5 @@
# The "testdata" part is added here because the test is actually run from the
# parent directory. Real interface files usually contain only absolute paths.
source ./testdata/ifaces
source ./testdata/*

View File

@@ -262,7 +262,8 @@ func (p *DefaultAddrProc) processRDNS(ip netip.Addr) (host string) {
// shouldResolve returns false if ip is a loopback address, or ip is private and
// resolving of private addresses is disabled.
func (p *DefaultAddrProc) shouldResolve(ip netip.Addr) (ok bool) {
return !ip.IsLoopback() && (p.usePrivateRDNS || !p.privateSubnets.Contains(ip))
return !ip.IsLoopback() &&
(p.usePrivateRDNS || !p.privateSubnets.Contains(ip.AsSlice()))
}
// processWHOIS looks up the information about clients' IP addresses in the

View File

@@ -7,8 +7,6 @@ package client
import (
"encoding"
"fmt"
"github.com/AdguardTeam/AdGuardHome/internal/whois"
)
// Source represents the source from which the information about the client has
@@ -17,7 +15,8 @@ type Source uint8
// Clients information sources. The order determines the priority.
const (
SourceWHOIS Source = iota + 1
SourceNone Source = iota
SourceWHOIS
SourceARP
SourceRDNS
SourceDHCP
@@ -53,107 +52,3 @@ var _ encoding.TextMarshaler = Source(0)
func (cs Source) MarshalText() (text []byte, err error) {
return []byte(cs.String()), nil
}
// Runtime is a client information from different sources.
type Runtime struct {
// whois is the filtered WHOIS information of a client.
whois *whois.Info
// arp is the ARP information of a client. nil indicates that there is no
// information from the source. Empty non-nil slice indicates that the data
// from the source is present, but empty.
arp []string
// rdns is the RDNS information of a client. nil indicates that there is no
// information from the source. Empty non-nil slice indicates that the data
// from the source is present, but empty.
rdns []string
// dhcp is the DHCP information of a client. nil indicates that there is no
// information from the source. Empty non-nil slice indicates that the data
// from the source is present, but empty.
dhcp []string
// hostsFile is the information from the hosts file. nil indicates that
// there is no information from the source. Empty non-nil slice indicates
// that the data from the source is present, but empty.
hostsFile []string
}
// Info returns a client information from the highest-priority source.
func (r *Runtime) Info() (cs Source, host string) {
info := []string{}
switch {
case r.hostsFile != nil:
cs, info = SourceHostsFile, r.hostsFile
case r.dhcp != nil:
cs, info = SourceDHCP, r.dhcp
case r.rdns != nil:
cs, info = SourceRDNS, r.rdns
case r.arp != nil:
cs, info = SourceARP, r.arp
case r.whois != nil:
cs = SourceWHOIS
}
if len(info) == 0 {
return cs, ""
}
// TODO(s.chzhen): Return the full information.
return cs, info[0]
}
// SetInfo sets a host as a client information from the cs.
func (r *Runtime) SetInfo(cs Source, hosts []string) {
if len(hosts) == 1 && hosts[0] == "" {
hosts = []string{}
}
switch cs {
case SourceARP:
r.arp = hosts
case SourceRDNS:
r.rdns = hosts
case SourceDHCP:
r.dhcp = hosts
case SourceHostsFile:
r.hostsFile = hosts
}
}
// WHOIS returns a WHOIS client information.
func (r *Runtime) WHOIS() (info *whois.Info) {
return r.whois
}
// SetWHOIS sets a WHOIS client information. info must be non-nil.
func (r *Runtime) SetWHOIS(info *whois.Info) {
r.whois = info
}
// Unset clears a cs information.
func (r *Runtime) Unset(cs Source) {
switch cs {
case SourceWHOIS:
r.whois = nil
case SourceARP:
r.arp = nil
case SourceRDNS:
r.rdns = nil
case SourceDHCP:
r.dhcp = nil
case SourceHostsFile:
r.hostsFile = nil
}
}
// IsEmpty returns true if there is no information from any source.
func (r *Runtime) IsEmpty() (ok bool) {
return r.whois == nil &&
r.arp == nil &&
r.rdns == nil &&
r.dhcp == nil &&
r.hostsFile == nil
}

View File

@@ -1,5 +0,0 @@
// Package configmigrate provides a way to upgrade the YAML configuration file.
package configmigrate
// LastSchemaVersion is the most recent schema version.
const LastSchemaVersion uint = 28

View File

@@ -1,47 +0,0 @@
package configmigrate
import (
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
)
// migrateTo28 performs the following changes:
//
// # BEFORE:
// 'dns':
// 'all_servers': true
// 'fastest_addr': true
// # …
// # …
//
// # AFTER:
// 'dns':
// 'upstream_mode': 'parallel'
// # …
// # …
func migrateTo28(diskConf yobj) (err error) {
diskConf["schema_version"] = 28
dns, ok, err := fieldVal[yobj](diskConf, "dns")
if !ok {
return err
}
allServers, _, _ := fieldVal[bool](dns, "all_servers")
fastestAddr, _, _ := fieldVal[bool](dns, "fastest_addr")
var upstreamModeType dnsforward.UpstreamMode
if allServers {
upstreamModeType = dnsforward.UpstreamModeParallel
} else if fastestAddr {
upstreamModeType = dnsforward.UpstreamModeFastestAddr
} else {
upstreamModeType = dnsforward.UpstreamModeLoadBalance
}
dns["upstream_mode"] = upstreamModeType
delete(dns, "all_servers")
delete(dns, "fastest_addr")
return nil
}

View File

@@ -1,10 +1,9 @@
package configmigrate
package confmigrate
import (
"testing"
"time"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
"github.com/AdguardTeam/golibs/testutil"
"github.com/AdguardTeam/golibs/timeutil"
@@ -1647,84 +1646,3 @@ func TestUpgradeSchema26to27(t *testing.T) {
})
}
}
func TestUpgradeSchema27to28(t *testing.T) {
const newSchemaVer = 28
testCases := []struct {
in yobj
want yobj
name string
}{{
name: "empty",
in: yobj{},
want: yobj{
"schema_version": newSchemaVer,
},
}, {
name: "load_balance",
in: yobj{
"dns": yobj{
"all_servers": false,
"fastest_addr": false,
},
},
want: yobj{
"dns": yobj{
"upstream_mode": dnsforward.UpstreamModeLoadBalance,
},
"schema_version": newSchemaVer,
},
}, {
name: "parallel",
in: yobj{
"dns": yobj{
"all_servers": true,
"fastest_addr": false,
},
},
want: yobj{
"dns": yobj{
"upstream_mode": dnsforward.UpstreamModeParallel,
},
"schema_version": newSchemaVer,
},
}, {
name: "parallel_fastest",
in: yobj{
"dns": yobj{
"all_servers": true,
"fastest_addr": true,
},
},
want: yobj{
"dns": yobj{
"upstream_mode": dnsforward.UpstreamModeParallel,
},
"schema_version": newSchemaVer,
},
}, {
name: "load_balance",
in: yobj{
"dns": yobj{
"all_servers": false,
"fastest_addr": true,
},
},
want: yobj{
"dns": yobj{
"upstream_mode": dnsforward.UpstreamModeFastestAddr,
},
"schema_version": newSchemaVer,
},
}}
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
err := migrateTo28(tc.in)
require.NoError(t, err)
assert.Equal(t, tc.want, tc.in)
})
}
}

View File

@@ -1,4 +1,5 @@
package configmigrate
// Package confmigrate provides a way to upgrade the YAML configuration file.
package confmigrate
import (
"bytes"
@@ -8,6 +9,9 @@ import (
yaml "gopkg.in/yaml.v3"
)
// LastSchemaVersion is the most recent schema version.
const LastSchemaVersion uint = 27
// Config is a the configuration for initializing a [Migrator].
type Config struct {
// WorkingDir is an absolute path to the working directory of AdGuardHome.
@@ -119,7 +123,6 @@ func (m *Migrator) upgradeConfigSchema(current, target uint, diskConf yobj) (err
24: migrateTo25,
25: migrateTo26,
26: migrateTo27,
27: migrateTo28,
}
for i, migrate := range upgrades[current:target] {

View File

@@ -1,4 +1,4 @@
package configmigrate_test
package confmigrate_test
import (
"io/fs"
@@ -6,7 +6,7 @@ import (
"path"
"testing"
"github.com/AdguardTeam/AdGuardHome/internal/configmigrate"
"github.com/AdguardTeam/AdGuardHome/internal/confmigrate"
"github.com/AdguardTeam/golibs/testutil"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/bcrypt"
@@ -200,7 +200,7 @@ func TestMigrateConfig_Migrate(t *testing.T) {
wantBody, err := fs.ReadFile(testdata, path.Join(t.Name(), outputFileName))
require.NoError(t, err)
migrator := configmigrate.New(&configmigrate.Config{
migrator := confmigrate.New(&confmigrate.Config{
WorkingDir: t.Name(),
})
newBody, upgraded, err := migrator.Migrate(body, tc.targetVersion)

Some files were not shown because too many files have changed in this diff Show More