Compare commits
59 Commits
v0.108.0-b
...
6263-custo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f6b704fb58 | ||
|
|
780d001cef | ||
|
|
5dd10d9fc6 | ||
|
|
820bcf0e23 | ||
|
|
1320043e95 | ||
|
|
f28dcefa29 | ||
|
|
8b9708b8e0 | ||
|
|
6eba447958 | ||
|
|
29cc387c5f | ||
|
|
73358263e8 | ||
|
|
cb9262dced | ||
|
|
e7ca515630 | ||
|
|
23392d08b1 | ||
|
|
a09cd190c0 | ||
|
|
feb15745d2 | ||
|
|
789060e4d4 | ||
|
|
0f5e8ca56f | ||
|
|
a700bfb42e | ||
|
|
7669419b59 | ||
|
|
db42254d76 | ||
|
|
4a9dc1d6c1 | ||
|
|
944e0d7a4b | ||
|
|
c8f1112d4e | ||
|
|
1c0bf95b5a | ||
|
|
388583cefe | ||
|
|
8bb1aad739 | ||
|
|
9b91a87406 | ||
|
|
94bceaa84d | ||
|
|
ebb06a5831 | ||
|
|
f44faa9be3 | ||
|
|
b1b5c41cfe | ||
|
|
37b69b2180 | ||
|
|
b1b7b1cfe9 | ||
|
|
fdf60eeed1 | ||
|
|
4b9947da88 | ||
|
|
53170d8711 | ||
|
|
d3862614e5 | ||
|
|
f8fe9bfc8b | ||
|
|
6cff5865d2 | ||
|
|
cbcc17a58b | ||
|
|
6a3906aa95 | ||
|
|
ffdebc7b2d | ||
|
|
f3817e4411 | ||
|
|
52713a2600 | ||
|
|
62ec0d5adc | ||
|
|
2a56c78f26 | ||
|
|
c0588146e7 | ||
|
|
f6e34adee7 | ||
|
|
e3cc3b0642 | ||
|
|
cd09ba63b6 | ||
|
|
1d1de1bfb5 | ||
|
|
763bbb5e6b | ||
|
|
9e9d0206b8 | ||
|
|
76899cc31e | ||
|
|
f514f365ab | ||
|
|
413f484810 | ||
|
|
733d6c1fca | ||
|
|
506d71310c | ||
|
|
bb652cd9a1 |
7
.github/PULL_REQUEST_TEMPLATE
vendored
7
.github/PULL_REQUEST_TEMPLATE
vendored
@@ -1,7 +1,8 @@
|
||||
Before submitting a PR please make sure that:
|
||||
|
||||
1. You have discussed your solution in an issue and have got an
|
||||
approval from a maintainer.
|
||||
approval from a maintainer. See our
|
||||
[contribution guide](https://github.com/AdguardTeam/AdGuardHome/blob/master/CONTRIBUTING.md).
|
||||
|
||||
2. This isn't a localization fix; please send those to our
|
||||
[CrowdIn](https://crowdin.com/project/adguard-applications/en#/adguard-home)
|
||||
@@ -13,8 +14,8 @@ Before submitting a PR please make sure that:
|
||||
Add a short description here. The description should include:
|
||||
|
||||
1. Which issue this PR closes (`Closes #NNNN.`) or updates (`Updates
|
||||
#NNNN.`).
|
||||
#NNNN.`). Please do not open PRs without filing an issue first.
|
||||
|
||||
2. A short description of how the change achieves that.
|
||||
|
||||
Do not forget to remove these instructions.
|
||||
Do not forget to remove these instructions!
|
||||
|
||||
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'build'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.20.10'
|
||||
'GO_VERSION': '1.20.11'
|
||||
'NODE_VERSION': '16'
|
||||
|
||||
'on':
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -1,7 +1,7 @@
|
||||
'name': 'lint'
|
||||
|
||||
'env':
|
||||
'GO_VERSION': '1.20.10'
|
||||
'GO_VERSION': '1.20.11'
|
||||
|
||||
'on':
|
||||
'push':
|
||||
|
||||
150
CHANGELOG.md
150
CHANGELOG.md
@@ -14,21 +14,136 @@ and this project adheres to
|
||||
<!--
|
||||
## [v0.108.0] - TBA
|
||||
|
||||
## [v0.107.40] - 2023-10-25 (APPROX.)
|
||||
## [v0.107.42] - 2023-12-06 (APPROX.)
|
||||
|
||||
See also the [v0.107.40 GitHub milestone][ms-v0.107.40].
|
||||
See also the [v0.107.42 GitHub milestone][ms-v0.107.42].
|
||||
|
||||
[ms-v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/milestone/75?closed=1
|
||||
[ms-v0.107.42]: https://github.com/AdguardTeam/AdGuardHome/milestone/77?closed=1
|
||||
|
||||
NOTE: Add new changes BELOW THIS COMMENT.
|
||||
-->
|
||||
|
||||
### Added
|
||||
|
||||
- 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 used ([#1660]).
|
||||
- Ability to specify rate limiting settings in the Web UI ([#6369]).
|
||||
|
||||
### Changed
|
||||
|
||||
#### Configuration changes
|
||||
|
||||
- The new property `dns.serve_plain_dns` has been added to the configuration
|
||||
file ([#1660]).
|
||||
- The property `dns.bogus_nxdomain` is now validated more strictly.
|
||||
- Added new properties `clients.persistent.*.upstreams_cache_enabled` and
|
||||
`clients.persistent.*.upstreams_cache_size` that describe cache configuration
|
||||
for each client's custom upstream configuration.
|
||||
|
||||
### Fixed
|
||||
|
||||
- `ipset` entries family validation ([#6420]).
|
||||
- Pre-filling the *New static lease* window with data ([#6402]).
|
||||
- Protection pause timer synchronization ([#5759]).
|
||||
|
||||
[#1660]: https://github.com/AdguardTeam/AdGuardHome/issues/1660
|
||||
[#5759]: https://github.com/AdguardTeam/AdGuardHome/issues/5759
|
||||
[#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
|
||||
|
||||
[dnsproxy#169] https://github.com/AdguardTeam/dnsproxy/issues/169
|
||||
|
||||
<!--
|
||||
NOTE: Add new changes ABOVE THIS COMMENT.
|
||||
-->
|
||||
|
||||
|
||||
|
||||
## [v0.107.41] - 2023-11-13
|
||||
|
||||
See also the [v0.107.41 GitHub milestone][ms-v0.107.41].
|
||||
|
||||
### Security
|
||||
|
||||
- Go version has been updated to prevent the possibility of exploiting the
|
||||
CVE-2023-45283 and CVE-2023-45284 Go vulnerabilities fixed in
|
||||
[Go 1.20.11][go-1.20.11].
|
||||
|
||||
### Added
|
||||
|
||||
- Ability to specify subnet lengths for IPv4 and IPv6 addresses, used for rate
|
||||
limiting requests, in the configuration file ([#6368]).
|
||||
- Ability to specify multiple domain specific upstreams per line, e.g.
|
||||
`[/domain1/../domain2/]upstream1 upstream2 .. upstreamN` ([#4977]).
|
||||
|
||||
### Changed
|
||||
|
||||
- Increased the height of the ready-to-use filter lists dialog ([#6358]).
|
||||
- Improved logging of authentication failures ([#6357]).
|
||||
|
||||
#### Configuration changes
|
||||
|
||||
- New properties `dns.ratelimit_subnet_len_ipv4` and
|
||||
`dns.ratelimit_subnet_len_ipv6` have been added to the configuration file
|
||||
([#6368]).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Schedule timezone not being sent ([#6401]).
|
||||
- Average request processing time calculation ([#6220]).
|
||||
- Redundant truncation of long client names in the Top Clients table ([#6338]).
|
||||
- Scrolling column headers in the tables ([#6337]).
|
||||
- `$important,dnsrewrite` rules not overriding allowlist rules ([#6204]).
|
||||
- Dark mode DNS rewrite background ([#6329]).
|
||||
- Issues with QUIC and HTTP/3 upstreams on Linux ([#6335]).
|
||||
|
||||
[#4977]: https://github.com/AdguardTeam/AdGuardHome/issues/4977
|
||||
[#6204]: https://github.com/AdguardTeam/AdGuardHome/issues/6204
|
||||
[#6220]: https://github.com/AdguardTeam/AdGuardHome/issues/6220
|
||||
[#6329]: https://github.com/AdguardTeam/AdGuardHome/issues/6329
|
||||
[#6335]: https://github.com/AdguardTeam/AdGuardHome/issues/6335
|
||||
[#6337]: https://github.com/AdguardTeam/AdGuardHome/issues/6337
|
||||
[#6338]: https://github.com/AdguardTeam/AdGuardHome/issues/6338
|
||||
[#6357]: https://github.com/AdguardTeam/AdGuardHome/issues/6357
|
||||
[#6358]: https://github.com/AdguardTeam/AdGuardHome/issues/6358
|
||||
[#6368]: https://github.com/AdguardTeam/AdGuardHome/issues/6368
|
||||
[#6401]: https://github.com/AdguardTeam/AdGuardHome/issues/6401
|
||||
|
||||
[go-1.20.11]: https://groups.google.com/g/golang-announce/c/4tU8LZfBFkY/m/d-jSKR_jBwAJ
|
||||
[ms-v0.107.41]: https://github.com/AdguardTeam/AdGuardHome/milestone/76?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.40] - 2023-10-18
|
||||
|
||||
See also the [v0.107.40 GitHub milestone][ms-v0.107.40].
|
||||
|
||||
### Changed
|
||||
|
||||
- *Block* and *Unblock* buttons of the query log moved to the tooltip menu
|
||||
([#684]).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Dashboard tables scroll issue ([#6180]).
|
||||
- The time shown in the statistics is one hour less than the current time
|
||||
([#6296]).
|
||||
- Issues with QUIC and HTTP/3 upstreams on FreeBSD ([#6301]).
|
||||
- Panic on clearing the query log ([#6304]).
|
||||
|
||||
[#684]: https://github.com/AdguardTeam/AdGuardHome/issues/684
|
||||
[#6180]: https://github.com/AdguardTeam/AdGuardHome/issues/6180
|
||||
[#6296]: https://github.com/AdguardTeam/AdGuardHome/issues/6296
|
||||
[#6301]: https://github.com/AdguardTeam/AdGuardHome/issues/6301
|
||||
[#6304]: https://github.com/AdguardTeam/AdGuardHome/issues/6304
|
||||
|
||||
[ms-v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/milestone/75?closed=1
|
||||
|
||||
|
||||
|
||||
## [v0.107.39] - 2023-10-11
|
||||
|
||||
See also the [v0.107.39 GitHub milestone][ms-v0.107.39].
|
||||
@@ -66,9 +181,8 @@ See also the [v0.107.39 GitHub milestone][ms-v0.107.39].
|
||||
[#6233]: https://github.com/AdguardTeam/AdGuardHome/issues/6233
|
||||
[#6280]: https://github.com/AdguardTeam/AdGuardHome/issues/6280
|
||||
|
||||
[go-1.20.9]: https://groups.google.com/g/golang-announce/c/XBa1oHDevAo/m/desYyx3qAgAJ
|
||||
[go-1.20.10]: https://groups.google.com/g/golang-announce/c/iNNxDTCjZvo/m/UDd7VKQuAAAJ
|
||||
|
||||
[go-1.20.10]: https://groups.google.com/g/golang-announce/c/iNNxDTCjZvo/m/UDd7VKQuAAAJ
|
||||
[go-1.20.9]: https://groups.google.com/g/golang-announce/c/XBa1oHDevAo/m/desYyx3qAgAJ
|
||||
[ms-v0.107.39]: https://github.com/AdguardTeam/AdGuardHome/milestone/74?closed=1
|
||||
|
||||
|
||||
@@ -130,7 +244,7 @@ See also the [v0.107.37 GitHub milestone][ms-v0.107.37].
|
||||
is returned if the blocking mode isn't set to `Null IP`. In previous versions
|
||||
it returned NXDOMAIN response in such cases.
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 24 to 27.
|
||||
|
||||
@@ -340,7 +454,7 @@ See also the [v0.107.34 GitHub milestone][ms-v0.107.34].
|
||||
|
||||
- Improved CPU and RAM consumption during updates of filtering-rule lists.
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 23 to 24.
|
||||
|
||||
@@ -420,7 +534,7 @@ See also the [v0.107.33 GitHub milestone][ms-v0.107.33].
|
||||
|
||||
### Changed
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 20 to 23.
|
||||
|
||||
@@ -685,7 +799,7 @@ See also the [v0.107.28 GitHub milestone][ms-v0.107.28].
|
||||
- ARPA domain names containing a subnet within private networks now also
|
||||
considered private, behaving closer to [RFC 6761][rfc6761] ([#5567]).
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 17 to 20.
|
||||
|
||||
@@ -825,7 +939,7 @@ See also the [v0.107.26 GitHub milestone][ms-v0.107.26].
|
||||
|
||||
### Changed
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
- Property `edns_client_subnet`, which in schema versions 16 and earlier used
|
||||
to be a part of the `dns` object, is now part of the `dns.edns_client_subnet`
|
||||
@@ -914,7 +1028,7 @@ See also the [v0.107.24 GitHub milestone][ms-v0.107.24].
|
||||
|
||||
### Changed
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 14 to 16.
|
||||
|
||||
@@ -1624,7 +1738,7 @@ See also the [v0.107.7 GitHub milestone][ms-v0.107.7].
|
||||
- The `dns.bogus_nxdomain` property in the configuration file now supports CIDR
|
||||
notation alongside IP addresses ([#1730]).
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 12 to 14.
|
||||
|
||||
@@ -1965,7 +2079,7 @@ See also the [v0.107.0 GitHub milestone][ms-v0.107.0].
|
||||
file, together with the new `group` and `user` properties ([#2763]).
|
||||
- Permissions on filter files are now `0o644` instead of `0o600` ([#3198]).
|
||||
|
||||
#### Configuration Changes
|
||||
#### Configuration changes
|
||||
|
||||
In this release, the schema version has changed from 10 to 12.
|
||||
|
||||
@@ -2531,11 +2645,13 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
|
||||
|
||||
|
||||
<!--
|
||||
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.40...HEAD
|
||||
[v0.107.40]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.39...v0.107.40
|
||||
[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.39...HEAD
|
||||
[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
|
||||
[v0.107.38]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.37...v0.107.38
|
||||
[v0.107.37]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.36...v0.107.37
|
||||
|
||||
89
CONTRIBUTING.md
Normal file
89
CONTRIBUTING.md
Normal file
@@ -0,0 +1,89 @@
|
||||
# Contributing to AdGuard Home
|
||||
|
||||
If you want to contribute to AdGuard Home by filing or commenting on an issue or
|
||||
opening a pull request, please follow the instructions below.
|
||||
|
||||
|
||||
|
||||
## General recommendations
|
||||
|
||||
Please don't:
|
||||
|
||||
* post comments like “+1” or “this”. Use the :+1: reaction on the issue
|
||||
instead, as this allows us to actually see the level of support for issues.
|
||||
|
||||
* file issues about localization errors or send localization updates as PRs.
|
||||
We're using [CrowdIn] to manage our translations and we generally update
|
||||
them before each Beta and Release build. You can learn more about
|
||||
translating AdGuard products [in our Knowledge Base][kb-trans].
|
||||
|
||||
* file issues about a particular filtering-rule list misbehaving. These are
|
||||
tracked through the [separate form for filtering issues][form].
|
||||
|
||||
* send updates to filtering-rule lists, such as the ones for the Blocked
|
||||
Services feature or the list of approved filtering-rule lists. We update
|
||||
them once before each Beta and Release build.
|
||||
|
||||
Please do:
|
||||
|
||||
* follow the template instructions and provide data for reproducing issues.
|
||||
|
||||
* write the title of your issue or pull request in English. Any language is
|
||||
fine in the body, but it is important to keep the title in English to make
|
||||
it easier for people and bots to look up duplicated issues.
|
||||
|
||||
[CrowdIn]: https://crowdin.com/project/adguard-applications/en#/adguard-home
|
||||
[form]: https://link.adtidy.org/forward.html?action=report&app=home&from=github
|
||||
[kb-trans]: https://kb.adguard.com/en/general/adguard-translations
|
||||
|
||||
|
||||
|
||||
## Issues
|
||||
|
||||
### Search first
|
||||
|
||||
Please make sure that the issue is not a duplicate or a question. If it's a
|
||||
duplicate, please react to the original issue with a thumbs up. If it's a
|
||||
question, please look through our [Wiki] and, if you haven't found the answer,
|
||||
post it to the GitHub [Discussions] page.
|
||||
|
||||
[Discussions]: https://github.com/AdguardTeam/AdGuardHome/discussions/categories/q-a
|
||||
[Wiki]: https://github.com/AdguardTeam/AdGuardHome/wiki
|
||||
|
||||
|
||||
|
||||
### Follow the issue template
|
||||
|
||||
Developers need to be able to reproduce the faulty behavior in order to fix an
|
||||
issue, so please make sure that you follow the instructions in the issue
|
||||
template carefully.
|
||||
|
||||
|
||||
|
||||
## Pull requests
|
||||
|
||||
### Discuss your changes first
|
||||
|
||||
Please discuss your changes by opening an issue. The maintainers should
|
||||
evaluate your proposal, and it's generally better if that's done before any code
|
||||
is written.
|
||||
|
||||
|
||||
|
||||
### Review your changes for style
|
||||
|
||||
We have a set of [code guidelines][hacking] that we expect the code to follow.
|
||||
Please make sure you follow it.
|
||||
|
||||
[hacking]: https://github.com/AdguardTeam/CodeGuidelines/blob/master/Go/Go.md
|
||||
|
||||
|
||||
|
||||
### Test your changes
|
||||
|
||||
Make sure that it passes linters and tests by running the corresponding Make
|
||||
targets. For backend changes, it's `make go-check`. For frontend, run
|
||||
`make js-lint`.
|
||||
|
||||
Additionally, a manual test is often required. While we're constantly working
|
||||
on improving our test suites, they're still not as good as we'd like them to be.
|
||||
@@ -201,7 +201,7 @@ opinion, this cannot be legitimately counted as a Pi-Hole's feature.
|
||||
| Cross-platform | ✅ | ❌ (not natively, only via Docker) |
|
||||
| Running as a DNS-over-HTTPS or DNS-over-TLS server | ✅ | ❌ (requires additional software) |
|
||||
| Blocking phishing and malware domains | ✅ | ❌ (requires non-default blocklists) |
|
||||
| Parental control (blocking adult domains) | ✅ | ❌ |
|
||||
| Parental control (blocking adult domains) | ✅ | ❌ (requires non-default blocklists) |
|
||||
| Force Safe search on search engines | ✅ | ❌ |
|
||||
| Per-client (device) configuration | ✅ | ✅ |
|
||||
| Access settings (choose who can use AGH DNS) | ✅ | ❌ |
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
# Make sure to sync any changes with the branch overrides below.
|
||||
'variables':
|
||||
'channel': 'edge'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.4'
|
||||
'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.4'
|
||||
'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.4'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
# Make sure to sync any changes with the branch overrides below.
|
||||
'variables':
|
||||
'channel': 'edge'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.4'
|
||||
'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.4'
|
||||
'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.4'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
'snapcraftChannel': 'candidate'
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
'key': 'AHBRTSPECS'
|
||||
'name': 'AdGuard Home - Build and run tests'
|
||||
'variables':
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.4'
|
||||
'dockerGo': 'adguard/golang-ubuntu:7.5'
|
||||
|
||||
'stages':
|
||||
- 'Tests':
|
||||
|
||||
@@ -119,7 +119,8 @@
|
||||
"stats_malware_phishing": "Заблакаваныя шкодныя і фішынгавыя сайты",
|
||||
"stats_adult": "Заблакаваныя «дарослыя» сайты",
|
||||
"stats_query_domain": "Часта запытаныя дамены",
|
||||
"for_last_24_hours": "за 24 гадзіны",
|
||||
"for_last_hours": "за апошнюю {{count}} гадзіну",
|
||||
"for_last_hours_plural": "за апошнія {{count}} гадзін",
|
||||
"for_last_days": "за апошні {{count}} дзень",
|
||||
"for_last_days_plural": "за апошнія {{count}} дзён",
|
||||
"stats_disabled": "Статыстыка была адключаная. Вы можаце ўключыць яго <0>на старонцы налад </0>.",
|
||||
@@ -134,14 +135,14 @@
|
||||
"no_upstreams_data_found": "Няма дадзеных аб upstream серверах",
|
||||
"number_of_dns_query_days": "Колькасць DNS-запытаў за апошні {{count}} дзень",
|
||||
"number_of_dns_query_days_plural": "Колькасць DNS запытаў, апрацаваных за апошнія {{count}} дзён",
|
||||
"number_of_dns_query_24_hours": "Колькасць DNS-запытаў за 24 гадзіны",
|
||||
"number_of_dns_query_hours": "Колькасць DNS-запытаў, апрацаваных за апошнюю {{count}} гадзіну",
|
||||
"number_of_dns_query_hours_plural": "Колькасць DNS-запытаў, апрацаваных за апошнія {{count}} гадзін",
|
||||
"number_of_dns_query_blocked_24_hours": "Колькасць DNS-запытаў, заблакаваных фільтрамі і блок-спісамі",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Колькасць DNS-запытаў, заблакаваных модулем Антыфішынгу AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Колькасць заблакаваных «сайтаў для дарослых»",
|
||||
"enforced_save_search": "Ужыты бяспечны пошук",
|
||||
"number_of_dns_query_to_safe_search": "Колькасць запытаў DNS для пошукавых сістэм, для якіх быў ужыты Бяспечны пошук",
|
||||
"average_processing_time": "Сярэдні час апрацоўкі запыту",
|
||||
"processing_time": "Час апрацоўкі",
|
||||
"average_processing_time_hint": "Сярэдні час для апрацоўкі запыту DNS у мілісекундах",
|
||||
"block_domain_use_filters_and_hosts": "Блакаваць дамены з выкарыстаннем фільтраў і файлаў хастоў",
|
||||
"filters_block_toggle_hint": "Вы можаце наладзіць правілы блакавання ў «<a>Фільтрах</a>».",
|
||||
@@ -306,6 +307,7 @@
|
||||
"edns_use_custom_ip": "Выкарыстоўваць указаны IP для DNS",
|
||||
"edns_use_custom_ip_desc": "Дазволіць выкарыстоўваць уласны IP для DNS",
|
||||
"rate_limit_desc": "Абмежаванне на колькасць запытаў у секунду для кожнага кліента (0 — неабмежавана)",
|
||||
"rate_limit_whitelist_placeholder": "Увядзіце па адным адрасе на радок",
|
||||
"blocking_ipv4_desc": "IP-адрас, што вяртаецца пры блакаванню A-запыту",
|
||||
"blocking_ipv6_desc": "IP-адрас, што вяртаецца пры блакаванню AAAA-запыту",
|
||||
"blocking_mode_default": "Стандартны: Адказвае з нулёвым IP-адрасам (0.0.0.0 для A; :: для AAAA), калі заблакавана правілам у стылі Adblock; адказвае з IP-адрасам, паказаным у правіле, калі заблакавана правілам у стылі /etc/hosts-style",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Nastavení klienta",
|
||||
"example_upstream_reserved": "odchozí DNS připojení <0>pro konkrétní doménu(y)</0>;",
|
||||
"example_multiple_upstreams_reserved": "více odchozích připojení <0>pro konkrétní domény</0>;",
|
||||
"example_upstream_comment": "komentář.",
|
||||
"upstream_parallel": "Použijte paralelní požadavky na urychlení řešení simultánním dotazováním na všechny navazující servery.",
|
||||
"parallel_requests": "Paralelní požadavky",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokovaný malware/podvody",
|
||||
"stats_adult": "Blokované stránky pro dospělé",
|
||||
"stats_query_domain": "Nejčastěji dotazované domény",
|
||||
"for_last_24_hours": "za posledních 24 hodin",
|
||||
"for_last_hours": "za poslední {{count}} hodinu",
|
||||
"for_last_hours_plural": "za posledních {{count}} hodin",
|
||||
"for_last_days": "za posledních {{count}} dní",
|
||||
"for_last_days_plural": "za posledních {{count}} dní",
|
||||
"stats_disabled": "Statistiky byly vypnuty. Můžete je zapnout ze <0>stránky nastavení</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nebyla nalezena žádná data odchozích připojení",
|
||||
"number_of_dns_query_days": "Počet DNS dotazů zpracovaných za posledních {{count}} den",
|
||||
"number_of_dns_query_days_plural": "Počet DNS dotazů zpracovaných za posledních {{count}} dní",
|
||||
"number_of_dns_query_24_hours": "Počet DNS dotazů zpracovaných za posledních 24 hodin",
|
||||
"number_of_dns_query_hours": "Počet DNS dotazů zpracovaných za poslední {{count}} hodinu",
|
||||
"number_of_dns_query_hours_plural": "Počet DNS dotazů zpracovaných za posledních {{count}} hodin",
|
||||
"number_of_dns_query_blocked_24_hours": "Počet požadavků DNS zablokovaných filtrem reklam a seznamy blokování hostitelů",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Počet požadavků DNS zablokovaných AdGuard modulem Bezpečné prohlížení",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Počet zablokovaných stránek pro dospělé",
|
||||
"enforced_save_search": "Vynucené bezpečné vyhledávání",
|
||||
"number_of_dns_query_to_safe_search": "Počet požadavků DNS na vyhledávače, při kterých bylo vynucené bezpečné vyhledávání",
|
||||
"average_processing_time": "Průměrný čas zpracování",
|
||||
"processing_time": "Doba zpracování",
|
||||
"average_upstream_response_time": "Průměrná doba odezvy odchozích připojení",
|
||||
"response_time": "Čas odezvy",
|
||||
"average_processing_time_hint": "Průměrný čas zpracování požadavků DNS v milisekundách",
|
||||
"block_domain_use_filters_and_hosts": "Blokovat domény pomocí filtrů a seznamů adres",
|
||||
"filters_block_toggle_hint": "Pravidla blokování můžete nastavit v nastavení <a>Filtry</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Použít vlastní IP pro EDNS",
|
||||
"edns_use_custom_ip_desc": "Povolit použití vlastní IP pro EDNS",
|
||||
"rate_limit_desc": "Počet požadavků za sekundu, které smí jeden klient provádět (0: neomezeno)",
|
||||
"rate_limit_subnet_len_ipv4": "Délka předpony podsítě pro adresy IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Délka předpony podsítě pro adresy IPv4 používané pro omezení rychlosti. Výchozí hodnota je 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Délka předpony podsítě IPv4 by měla být mezi 0 a 32",
|
||||
"rate_limit_subnet_len_ipv6": "Délka předpony podsítě pro adresy IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Délka předpony podsítě pro adresy IPv6 používané pro omezení rychlosti. Výchozí hodnota je 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Délka předpony podsítě IPv6 by měla být mezi 0 a 128",
|
||||
"form_enter_rate_limit_subnet_len": "Zadejte délku předpony podsítě pro omezení rychlosti",
|
||||
"rate_limit_whitelist": "Seznam výjimek pro omezení rychlosti",
|
||||
"rate_limit_whitelist_desc": "IP adresy vyloučené z omezení rychlosti",
|
||||
"rate_limit_whitelist_placeholder": "Zadejte jednu IP adresu na řádek",
|
||||
"blocking_ipv4_desc": "IP adresa, která se má vrátit v případě blokovaného požadavku typu A",
|
||||
"blocking_ipv6_desc": "IP adresa, která se má vrátit v případě blokovaného požadavku typu AAAA",
|
||||
"blocking_mode_default": "Výchozí: Odezva s nulovou IP adresou (0.0.0.0 pro A; :: pro AAAA), pokud je blokováno pravidlem ve stylu Adblock; odezva pomocí IP adresy uvedené v pravidle, pokud je blokováno pravidlem /etc/hosts-style",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Klientindstillinger",
|
||||
"example_upstream_reserved": "en upstream <0>for bestemte domæner</0>;",
|
||||
"example_multiple_upstreams_reserved": "flere upstreams <0>til bestemte domæner</0>;",
|
||||
"example_upstream_comment": "en kommentaren.",
|
||||
"upstream_parallel": "Brug parallelforespørgsler til at accelerere fortolkningen ved at forespørge alle upstream-servere samtidigt.",
|
||||
"parallel_requests": "Parallelle forespørgsler",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokeret malware/phishing",
|
||||
"stats_adult": "Blokerede voksne websteder",
|
||||
"stats_query_domain": "Mest forespurgte domæner",
|
||||
"for_last_24_hours": "de seneste 24 timer",
|
||||
"for_last_hours": "den seneste {{count}} time",
|
||||
"for_last_hours_plural": "de seneste {{count}} timer",
|
||||
"for_last_days": "den seneste {{count}} dag",
|
||||
"for_last_days_plural": "de seneste {{count}} dage",
|
||||
"stats_disabled": "Statistikker er deaktiveret. De kan aktiveres via <0>indstillingssiden</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Ingen upstreams-data fundet",
|
||||
"number_of_dns_query_days": "Antallet af DNS-forespørgsler behandlet den seneste {{count}} dag",
|
||||
"number_of_dns_query_days_plural": "Antallet af DNS-forespørgsler behandlet de seneste {{count}} dage",
|
||||
"number_of_dns_query_24_hours": "Antallet af DNS-forespørgsler behandlet de seneste 24 timer",
|
||||
"number_of_dns_query_hours": "Antallet af DNS-forespørgsler behandlet den seneste {{count}} time",
|
||||
"number_of_dns_query_hours_plural": "Antallet af DNS-forespørgsler behandlet de seneste {{count}} timer",
|
||||
"number_of_dns_query_blocked_24_hours": "Antallet af DNS-forespørgsler blokeret af adblockfiltre og værtssortlister",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Antallet af DNS-forespørgsler blokeret af AdGuards browsingsikkerhedsmodul",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Antallet af blokerede voksenwebsteder",
|
||||
"enforced_save_search": "Håndhævet sikker søgning",
|
||||
"number_of_dns_query_to_safe_search": "Antallet af DNS-forespørgsler til søgemaskiner, hvor Sikker Søgning blev håndhævet",
|
||||
"average_processing_time": "Gennemsnitlig behandlingstid",
|
||||
"processing_time": "Behandlingstid",
|
||||
"average_upstream_response_time": "Gennemsnitlig upstream-responstid",
|
||||
"response_time": "Responstid",
|
||||
"average_processing_time_hint": "Gennemsnitlig behandlingstid i millisekunder af DNS-forespørgsel",
|
||||
"block_domain_use_filters_and_hosts": "Blokér domæner vha. filtre og værtsfiler",
|
||||
"filters_block_toggle_hint": "Du kan opsætte blokeringsregler i <a>Filterindstillingerne</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Brug tilpasset IP til EDNS",
|
||||
"edns_use_custom_ip_desc": "Tillad brug af tilpasset IP til EDNS",
|
||||
"rate_limit_desc": "Antallet af forespørgsler pr. sekund tilladt pr. klient (værdien 0 = ubegrænset)",
|
||||
"rate_limit_subnet_len_ipv4": "Længde på undernetpræfiks for IPv4-adresser",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Længde på undernetpræfiks for IPv4-adresser til hastighedsbegrænsning. Standard er 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Længden på IPv4-undernetpræfiks skal være mellem 0 og 32",
|
||||
"rate_limit_subnet_len_ipv6": "Længde på undernetpræfiks for IPv6-adresser",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Længde på undernetpræfiks for IPv6-adresser til hastighedsbegrænsning. Standard er 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Længden på IPv6-undernetpræfiks skal være mellem 0 og 128",
|
||||
"form_enter_rate_limit_subnet_len": "Angiv længden på undernetpræfiks til hastighedsbegrænsning",
|
||||
"rate_limit_whitelist": "Hvidliste til hastighedsbegrænsning",
|
||||
"rate_limit_whitelist_desc": "IP-adresser undtaget fra hastighedsbegrænsning",
|
||||
"rate_limit_whitelist_placeholder": "Angiv én IP-adresse pr. linje",
|
||||
"blocking_ipv4_desc": "Returneret IP-adresse for en blokeret A-forespørgsel",
|
||||
"blocking_ipv6_desc": "Returneret IP-adresse for en blokeret AAAA-forespørgsel",
|
||||
"blocking_mode_default": "Standard: Svar med nul IP-adresse (0.0.0.0 for A; :: for AAAA), når blokeret af Adblock-lignende regel. Svar med IP-adressen angivet i reglen, når blokeret af /etc/hosts-lignende regel",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Client-Einstellungen",
|
||||
"example_upstream_reserved": "ein Upstream <0>für bestimmte Domains</0>;",
|
||||
"example_multiple_upstreams_reserved": "mehrere Upstreams <0>für bestimmte Domains</0>;",
|
||||
"example_upstream_comment": "ein Kommentar.",
|
||||
"upstream_parallel": "Parallele Abfragen verwenden, um das Auflösen zu beschleunigen, indem alle Upstream-Server gleichzeitig abgefragt werden.",
|
||||
"parallel_requests": "Paralleles Abfragen",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Gesperrte Schädliche/Phishing-Websites",
|
||||
"stats_adult": "Gesperrte jugendgefährdende Websites",
|
||||
"stats_query_domain": "Am häufigsten angefragte Domains",
|
||||
"for_last_24_hours": "für die letzten 24 Stunden",
|
||||
"for_last_hours": "in die letzte {{count}} Stunde",
|
||||
"for_last_hours_plural": "in die letzten {{count}} Stunden",
|
||||
"for_last_days": "am letzten {{count}} Tag",
|
||||
"for_last_days_plural": "in den letzten {{count}} Tage",
|
||||
"stats_disabled": "Die Statistik wurde deaktiviert. Sie können diese in den <0>Einstellungen</0> erneut aktivieren.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Keine Upstream-Daten gefunden",
|
||||
"number_of_dns_query_days": "Anzahl der in den letzten {{count}} Tagen verarbeiteten DNS-Anfragen",
|
||||
"number_of_dns_query_days_plural": "Anzahl der DNS-Abfragen, die in den letzten {{count}} Tagen verarbeitet wurden",
|
||||
"number_of_dns_query_24_hours": "Anzahl der in den letzten 24 Stunden durchgeführten DNS-Anfragen",
|
||||
"number_of_dns_query_hours": "Die Anzahl der DNS-Anfragen, die in der letzten {{count}} Stunde verarbeitet wurden",
|
||||
"number_of_dns_query_hours_plural": "Die Anzahl der DNS-Anfragen, die in den letzten {{count}} Stunden verarbeitet wurden",
|
||||
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Sperrlisten abgelehnte DNS-Anfragen",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul „Internetsicherheit“ gesperrten DNS-Anfragen",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Anzahl der gesperrten Websites mit jugendgefährdenden Inhalten",
|
||||
"enforced_save_search": "Sichere Suche erzwungen",
|
||||
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen Sichere Suche für Suchanfragen erzwungen wurde",
|
||||
"average_processing_time": "Durchschnittliche Bearbeitungsdauer",
|
||||
"processing_time": "Verarbeitungszeit",
|
||||
"average_upstream_response_time": "Durchschnittliche Upstream-Antwortzeit",
|
||||
"response_time": "Antwortzeit",
|
||||
"average_processing_time_hint": "Durchschnittliche Zeit in Millisekunden zur Bearbeitung von DNS-Anfragen",
|
||||
"block_domain_use_filters_and_hosts": "Domains durch Filter und Host-Dateien sperren",
|
||||
"filters_block_toggle_hint": "Sie können Blockierregeln in den <a>Filter</a>einstellungen erstellen.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Benutzerdefinierte IP für EDNS verwenden",
|
||||
"edns_use_custom_ip_desc": "Benutzerdefinierte IP für EDNS zulassen",
|
||||
"rate_limit_desc": "Die Anzahl der Anfragen pro Sekunde, die ein einzelner Client stellen darf. Das Setzen auf 0 bedeutet keine Begrenzung.",
|
||||
"rate_limit_subnet_len_ipv4": "Länge des Subnetzpräfixes für IPv4-Adressen",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Subnetpräfixlänge für IPv4-Adressen, die für die Ratebegrenzung verwendet werden. Der Standardwert ist 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Die Subnetzpräfixlänge für IPv4-Adressen sollte zwischen 0 und 32 liegen",
|
||||
"rate_limit_subnet_len_ipv6": "Subnetzpräfixlänge für IPv6-Adressen",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Subnetpräfixlänge für IPv6-Adressen, die für die Ratebegrenzung verwendet werden. Der Standardwert ist 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Die Subnetzpräfixlänge für IPv6-Adressen sollte zwischen 0 und 128 liegen",
|
||||
"form_enter_rate_limit_subnet_len": "Geben Sie die Subnetzpräfixlänge für die Ratebegrenzung ein",
|
||||
"rate_limit_whitelist": "Zulassungsliste für die Ratebegrenzung",
|
||||
"rate_limit_whitelist_desc": "IP-Adressen, die von der Ratebegrenzung ausgeschlossen sind",
|
||||
"rate_limit_whitelist_placeholder": "Geben Sie eine IP-Adresse pro Zeile ein",
|
||||
"blocking_ipv4_desc": "IP-Adresse, die für eine gesperrte A-Anfrage zurückgegeben werden soll",
|
||||
"blocking_ipv6_desc": "IP-Adresse, die für eine gesperrte AAAA-Anfrage zurückgegeben werden soll",
|
||||
"blocking_mode_default": "Standard: Mit Null IP Adress (0.0.0.0 for A; :: for AAAA) antworten, wenn sie durch eine Regel im Adblock-Stil gesperrt sind; mit der in der Regel angegebenen IP-Adresse antworten, wenn sie durch eine Regel im /etc/hosts-Stil gesperrt wurde",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Client settings",
|
||||
"example_upstream_reserved": "an upstream <0>for specific domains</0>;",
|
||||
"example_multiple_upstreams_reserved": "multiple upstreams <0>for specific domains</0>;",
|
||||
"example_upstream_comment": "a comment.",
|
||||
"upstream_parallel": "Use parallel queries to speed up resolving by querying all upstream servers simultaneously.",
|
||||
"parallel_requests": "Parallel requests",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blocked malware/phishing",
|
||||
"stats_adult": "Blocked adult websites",
|
||||
"stats_query_domain": "Top queried domains",
|
||||
"for_last_24_hours": "for the last 24 hours",
|
||||
"for_last_hours": "for the last {{count}} hour",
|
||||
"for_last_hours_plural": "for the last {{count}} hours",
|
||||
"for_last_days": "for the last {{count}} day",
|
||||
"for_last_days_plural": "for the last {{count}} days",
|
||||
"stats_disabled": "The statistics have been disabled. You can turn it on from the <0>settings page</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "No upstreams data found",
|
||||
"number_of_dns_query_days": "The number of DNS queries processed for the last {{count}} day",
|
||||
"number_of_dns_query_days_plural": "The number of DNS queries processed for the last {{count}} days",
|
||||
"number_of_dns_query_24_hours": "The number of DNS queries processed for the last 24 hours",
|
||||
"number_of_dns_query_hours": "The number of DNS queries processed for the last {{count}} hour",
|
||||
"number_of_dns_query_hours_plural": "The number of DNS queries processed for the last {{count}} hours",
|
||||
"number_of_dns_query_blocked_24_hours": "The number of DNS requests blocked by adblock filters and hosts blocklists",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "The number of DNS requests blocked by the AdGuard browsing security module",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "The number of adult websites blocked",
|
||||
"enforced_save_search": "Enforced safe search",
|
||||
"number_of_dns_query_to_safe_search": "The number of DNS requests to search engines for which Safe Search was enforced",
|
||||
"average_processing_time": "Average processing time",
|
||||
"processing_time": "Processing time",
|
||||
"average_upstream_response_time": "Average upstream response time",
|
||||
"response_time": "Response time",
|
||||
"average_processing_time_hint": "Average time in milliseconds on processing a DNS request",
|
||||
"block_domain_use_filters_and_hosts": "Block domains using filters and hosts files",
|
||||
"filters_block_toggle_hint": "You can setup blocking rules in the <a>Filters</a> settings.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Use custom IP for EDNS",
|
||||
"edns_use_custom_ip_desc": "Allow to use custom IP for EDNS",
|
||||
"rate_limit_desc": "The number of requests per second allowed per client. Setting it to 0 means no limit.",
|
||||
"rate_limit_subnet_len_ipv4": "Subnet prefix length for IPv4 addresses",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Subnet prefix length for IPv4 addresses used for rate limiting. The default is 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "The IPv4 subnet prefix length should be between 0 and 32",
|
||||
"rate_limit_subnet_len_ipv6": "Subnet prefix length for IPv6 addresses",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Subnet prefix length for IPv6 addresses used for rate limiting. The default is 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "The IPv6 subnet prefix length should be between 0 and 128",
|
||||
"form_enter_rate_limit_subnet_len": "Enter subnet prefix length for rate limiting",
|
||||
"rate_limit_whitelist": "Rate limiting allowlist",
|
||||
"rate_limit_whitelist_desc": "IP addresses excluded from rate limiting",
|
||||
"rate_limit_whitelist_placeholder": "Enter one IP address per line",
|
||||
"blocking_ipv4_desc": "IP address to be returned for a blocked A request",
|
||||
"blocking_ipv6_desc": "IP address to be returned for a blocked AAAA request",
|
||||
"blocking_mode_default": "Default: Respond with zero IP address (0.0.0.0 for A; :: for AAAA) when blocked by Adblock-style rule; respond with the IP address specified in the rule when blocked by /etc/hosts-style rule",
|
||||
@@ -720,5 +734,8 @@
|
||||
"wednesday_short": "Wed",
|
||||
"thursday_short": "Thu",
|
||||
"friday_short": "Fri",
|
||||
"saturday_short": "Sat"
|
||||
"saturday_short": "Sat",
|
||||
"upstream_dns_cache_configuration": "Upstream DNS cache configuration",
|
||||
"enable_upstream_dns_cache": "Enable DNS caching for this client's custom upstream configuration",
|
||||
"dns_cache_size": "DNS cache size, in bytes"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Configuración de clientes",
|
||||
"example_upstream_reserved": "un DNS de subida <0>para un dominio específico</0>.",
|
||||
"example_multiple_upstreams_reserved": "múltiples upstreams <0>para dominios específicos</0>;",
|
||||
"example_upstream_comment": "un comentario.",
|
||||
"upstream_parallel": "Usar consultas paralelas para acelerar la resolución al consultar simultáneamente a todos los servidores DNS de subida.",
|
||||
"parallel_requests": "Consultas paralelas",
|
||||
@@ -8,9 +9,9 @@
|
||||
"load_balancing_desc": "Consulta un servidor DNS de subida a la vez. AdGuard Home utiliza su algoritmo aleatorio ponderado para elegir el servidor más rápido y sea utilizado con más frecuencia.",
|
||||
"bootstrap_dns": "Servidores DNS de arranque",
|
||||
"bootstrap_dns_desc": "Direcciones IP de servidores DNS utilizadas para resolver direcciones IP de los solucionadores DoH/DoT que especifiques como ascendentes. No se permiten comentarios.",
|
||||
"fallback_dns_title": "Servidores DNS de fallback",
|
||||
"fallback_dns_desc": "La lista de DNS de fallback serán usadas cuando los servidores de upstream de DNS no respondan. La sintaxis es la misma que en los principales del campo anterior.",
|
||||
"fallback_dns_placeholder": "Ingresa un servidor de DNS alternativo por línea",
|
||||
"fallback_dns_title": "Servidores DNS alternativos",
|
||||
"fallback_dns_desc": "Lista de servidores DNS alternativos utilizados cuando los servidores DNS de subida no responden. La sintaxis es la misma que en el campo de los principales DNS de subida anterior.",
|
||||
"fallback_dns_placeholder": "Ingresa un servidor DNS alternativo por línea",
|
||||
"local_ptr_title": "Servidores DNS inversos y privados",
|
||||
"local_ptr_desc": "Los servidores DNS que AdGuard Home utiliza para las consultas PTR locales. Estos servidores se utilizan para resolver las peticiones PTR de direcciones en rangos de IP privadas, por ejemplo \"192.168.12.34\", utilizando DNS inverso. Si no está establecido, AdGuard Home utilizará los resolutores DNS predeterminados de tu sistema operativo, excepto las direcciones del propio AdGuard Home.",
|
||||
"local_ptr_default_resolver": "Por defecto, AdGuard Home utiliza los siguientes resolutores DNS inversos: {{ip}}.",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Malware/phishing bloqueado",
|
||||
"stats_adult": "Sitios web para adultos bloqueado",
|
||||
"stats_query_domain": "Dominios más consultados",
|
||||
"for_last_24_hours": "en las últimas 24 horas",
|
||||
"for_last_hours": "de la última {{count}} hora",
|
||||
"for_last_hours_plural": "de las últimas {{count}} horas",
|
||||
"for_last_days": "durante los últimos {{count}} días",
|
||||
"for_last_days_plural": "durante los últimos {{count}} días",
|
||||
"stats_disabled": "Las estadísticas se han deshabilitado. Puedes habilitarlas desde la <0>página de configuración</0>.",
|
||||
@@ -130,18 +132,20 @@
|
||||
"top_clients": "Clientes más frecuentes",
|
||||
"no_clients_found": "No se han encontrado clientes",
|
||||
"general_statistics": "Estadísticas generales",
|
||||
"top_upstreams": "Mejores upstreams",
|
||||
"no_upstreams_data_found": "No se han encontrado datos de upstreams",
|
||||
"top_upstreams": "DNS de subida más frecuentes",
|
||||
"no_upstreams_data_found": "No se han encontrado datos de DNS de subida",
|
||||
"number_of_dns_query_days": "Número de consultas DNS procesadas durante el último {{count}} día",
|
||||
"number_of_dns_query_days_plural": "Número de consultas DNS procesadas durante los últimos {{count}} días",
|
||||
"number_of_dns_query_24_hours": "Número de consultas DNS procesadas durante las últimas 24 horas",
|
||||
"number_of_dns_query_hours": "Número de consultas DNS procesadas durante la última {{count}} hora",
|
||||
"number_of_dns_query_hours_plural": "Número de consultas DNS procesadas durante las últimas {{count}} horas",
|
||||
"number_of_dns_query_blocked_24_hours": "Número de peticiones DNS bloqueadas por los filtros y listas de bloqueo de hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Número de peticiones DNS bloqueadas por el módulo de seguridad de navegación de AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Número de sitios web para adultos bloqueado",
|
||||
"enforced_save_search": "Búsquedas seguras forzadas",
|
||||
"number_of_dns_query_to_safe_search": "Número de peticiones DNS a los motores de búsqueda para los que se aplicó la búsqueda segura forzada",
|
||||
"average_processing_time": "Tiempo promedio de procesamiento",
|
||||
"processing_time": "Tiempo de procesamiento",
|
||||
"average_upstream_response_time": "Tiempo promedio de respuesta upstream",
|
||||
"response_time": "Tiempo de respuesta",
|
||||
"average_processing_time_hint": "Tiempo promedio en milisegundos al procesar una petición DNS",
|
||||
"block_domain_use_filters_and_hosts": "Bloquear dominios usando filtros y archivos hosts",
|
||||
"filters_block_toggle_hint": "Puedes configurar las reglas de bloqueo en la configuración de <a>filtros</a>.",
|
||||
@@ -166,7 +170,7 @@
|
||||
"upstream_dns_configured_in_file": "Configurado en {{path}}",
|
||||
"test_upstream_btn": "Probar DNS de subida",
|
||||
"upstreams": "DNS de subida",
|
||||
"upstream": "Upstream",
|
||||
"upstream": "DNS de subida",
|
||||
"apply_btn": "Aplicar",
|
||||
"disabled_filtering_toast": "Filtrado deshabilitado",
|
||||
"enabled_filtering_toast": "Filtrado habilitado",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Usar IP personalizada para EDNS",
|
||||
"edns_use_custom_ip_desc": "Permitir el uso de IP personalizadas para EDNS",
|
||||
"rate_limit_desc": "Número de peticiones por segundo permitidas por cliente. Establecerlo en 0 significa que no hay límite.",
|
||||
"rate_limit_subnet_len_ipv4": "Longitud del prefijo de subred para direcciones IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Longitud del prefijo de subred para direcciones IPv4 utilizadas para limitar la velocidad. El valor predeterminado es 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "La longitud del prefijo de subred IPv4 debe estar entre 0 y 32",
|
||||
"rate_limit_subnet_len_ipv6": "Longitud del prefijo de subred para direcciones IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Longitud del prefijo de subred para direcciones IPv6 utilizadas para limitar la velocidad. El valor predeterminado es 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "La longitud del prefijo de subred IPv6 debe estar entre 0 y 128",
|
||||
"form_enter_rate_limit_subnet_len": "Ingresa la longitud del prefijo de subred para limitar la velocidad",
|
||||
"rate_limit_whitelist": "Lista de permitidos de limitación de velocidad",
|
||||
"rate_limit_whitelist_desc": "Direcciones IP excluidas de la limitación de velocidad",
|
||||
"rate_limit_whitelist_placeholder": "Ingresa una dirección IP por línea",
|
||||
"blocking_ipv4_desc": "Dirección IP devolverá una petición A bloqueada",
|
||||
"blocking_ipv6_desc": "Dirección IP devolverá una petición AAAA bloqueada",
|
||||
"blocking_mode_default": "Predeterminado: Responde con dirección IP cero (0.0.0.0 para A; :: para AAAA) cuando está bloqueado por la regla de estilo Adblock; responde con la dirección IP especificada en la regla cuando está bloqueado por una regla de estilo /etc/hosts",
|
||||
@@ -675,21 +689,21 @@
|
||||
"disable_for_hours": "Por {{count}} hora",
|
||||
"disable_for_hours_plural": "Por {{count}} horas",
|
||||
"disable_until_tomorrow": "Hasta mañana",
|
||||
"disable_notify_for_seconds": "Desactivar la protección por {{count}} segundo",
|
||||
"disable_notify_for_seconds_plural": "Desactivar la protección por {{count}} segundos",
|
||||
"disable_notify_for_minutes": "Desactivar la protección por {{count}} minuto",
|
||||
"disable_notify_for_minutes_plural": "Desactivar la protección por {{count}} minutos",
|
||||
"disable_notify_for_hours": "Desactivar la protección por {{count}} hora",
|
||||
"disable_notify_for_hours_plural": "Desactivar la protección por {{count}} horas",
|
||||
"disable_notify_until_tomorrow": "Desactivar la protección hasta mañana",
|
||||
"enable_protection_timer": "La protección se activará en {{time}}",
|
||||
"disable_notify_for_seconds": "Deshabilitar protección por {{count}} segundo",
|
||||
"disable_notify_for_seconds_plural": "Deshabilitar protección por {{count}} segundos",
|
||||
"disable_notify_for_minutes": "Deshabilitar protección por {{count}} minuto",
|
||||
"disable_notify_for_minutes_plural": "Deshabilitar protección por {{count}} minutos",
|
||||
"disable_notify_for_hours": "Deshabilitar protección por {{count}} hora",
|
||||
"disable_notify_for_hours_plural": "Deshabilitar protección por {{count}} horas",
|
||||
"disable_notify_until_tomorrow": "Deshabilitar protección hasta mañana",
|
||||
"enable_protection_timer": "La protección se habilitará a las {{time}}",
|
||||
"custom_retention_input": "Ingresa la retención en horas",
|
||||
"custom_rotation_input": "Ingresa la rotación en horas",
|
||||
"protection_section_label": "Protección",
|
||||
"log_and_stats_section_label": "Registro de consultas y estadísticas",
|
||||
"ignore_query_log": "Ignorar este cliente en el registro de consultas",
|
||||
"ignore_statistics": "Ignorar este cliente en las estadísticas",
|
||||
"schedule_services": "Pausar el servicio de bloqueo",
|
||||
"schedule_services": "Pausar servicio de bloqueo",
|
||||
"schedule_services_desc": "Configura el horario programado de pausa del servicio de bloqueo",
|
||||
"schedule_services_desc_client": "Configurar el horario programado de pausa del bloqueo de servicio filtrado para este cliente",
|
||||
"schedule_desc": "Establecer periodos de inactividad para servicios bloqueados",
|
||||
@@ -699,7 +713,7 @@
|
||||
"schedule_current_timezone": "Zona horaria actual: {{value}}",
|
||||
"schedule_time_all_day": "Todo el dia",
|
||||
"schedule_modal_description": "Este horario sustituirá cualquier horario existente para el mismo día de la semana. Cada día de la semana solo puede tener un periodo de inactividad.",
|
||||
"schedule_modal_time_off": "Detener el servicio de bloqueo:",
|
||||
"schedule_modal_time_off": "Detener servicio de bloqueo:",
|
||||
"schedule_new": "Nuevo horario",
|
||||
"schedule_edit": "Editar horario",
|
||||
"schedule_save": "Guardar horario",
|
||||
|
||||
@@ -139,7 +139,6 @@
|
||||
"enforced_save_search": "جستجوی اَمن اجبار شده",
|
||||
"number_of_dns_query_to_safe_search": "تعداد درخواست های DNS برای موتور جستجو که جستجوی اَمن اجبار شده",
|
||||
"average_processing_time": "میانگین زمان پردازش",
|
||||
"processing_time": "زمان پردازش",
|
||||
"average_processing_time_hint": "زمان میانگین بر هزارم ثانیه در پردازش درخواست DNS",
|
||||
"block_domain_use_filters_and_hosts": "مسدودسازی دامنه ها توسط فیلترها و فایل های میزبان",
|
||||
"filters_block_toggle_hint": "میتوانید دستورات مسدودسازی را در تنظیمات <a>فیلترها</a> راه اندازی کنید.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Päätelaiteasetukset",
|
||||
"example_upstream_reserved": "ylävirta <0>tietyille verkkotunnuksille</0>;",
|
||||
"example_multiple_upstreams_reserved": "useita ylävirtoja <0>tietyille verkkotunnuksille</0>;",
|
||||
"example_upstream_comment": "kommentti.",
|
||||
"upstream_parallel": "Käytä rinnakkaisia pyyntöjä ja nopeuta selvitystä käyttämällä kaikkia ylävirtapalvelimia samanaikaisesti.",
|
||||
"parallel_requests": "Rinnakkaiset pyynnöt",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Estetyt haittaohjelmat/tietojenkalastelut",
|
||||
"stats_adult": "Estetyt aikuisille tarkoitetut sivustot",
|
||||
"stats_query_domain": "Kysytyimmät verkkotunnukset",
|
||||
"for_last_24_hours": "viimeisten 24 tunnin ajalta",
|
||||
"for_last_hours": "viimeisen {{count}} tunnin ajalta",
|
||||
"for_last_hours_plural": "viimeisen {{count}} tunnin ajalta",
|
||||
"for_last_days": "viimeisten {{count}} päivän ajalta",
|
||||
"for_last_days_plural": "viimeisten {{count}} päivän ajalta",
|
||||
"stats_disabled": "Tilastointi ei ole käytössä. Voit ottaa sen käyttöön <0>asetuksista</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Ylävirtatietoja ei löytynyt",
|
||||
"number_of_dns_query_days": "Käsiteltyjen DNS-pyyntöjen määrä viimeisten {{count}} päivän ajalta",
|
||||
"number_of_dns_query_days_plural": "Käsiteltyjen DNS-pyyntöjen määrä viimeisten {{count}} päivän ajalta",
|
||||
"number_of_dns_query_24_hours": "Käsiteltyjen DNS-pyyntöjen määrä viimeisten 24 tunnin ajalta",
|
||||
"number_of_dns_query_hours": "Viimeisen {{count}} tunnin aikana käsiteltyjen DNS-kyselyiden määrä",
|
||||
"number_of_dns_query_hours_plural": "Viimeisen {{count}} tunnin aikana käsiteltyjen DNS-kyselyiden määrä",
|
||||
"number_of_dns_query_blocked_24_hours": "Mainoseston suodattimien ja hosts-estolistojen estämien DNS-pyyntöjen määrä",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "AdGuardin Turvallinen selaus -moduulin estämien DNS-pyyntöjen määrä",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Estettyjen aikuisille tarkoitettujen sivustojen määrä",
|
||||
"enforced_save_search": "Turvallinen haku pakotettiin",
|
||||
"number_of_dns_query_to_safe_search": "DNS-pyyntöjen määrä, joille turvallinen haku pakotettiin käyttöön",
|
||||
"average_processing_time": "Keskimääräinen käsittelyaika",
|
||||
"processing_time": "Käsittelyaika",
|
||||
"average_upstream_response_time": "Ylävirran keskimääräinen vasteaika",
|
||||
"response_time": "Vasteaika",
|
||||
"average_processing_time_hint": "Keskimääräinen DNS-pyynnön käsittelyyn kulutettu aika millisekunteina",
|
||||
"block_domain_use_filters_and_hosts": "Estä verkkotunnuksia suodattimilla ja hosts-tiedostoilla",
|
||||
"filters_block_toggle_hint": "Voit määrittää estosääntöjä <a>suodatinasetuksissa</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Käytä omaa IP-osoitetta EDNS:lle",
|
||||
"edns_use_custom_ip_desc": "Salli oman IP-osoitteen käyttö EDNS-mekanismille.",
|
||||
"rate_limit_desc": "Päätelaitteelle sallittu pyyntöjen enimmäismäärä sekunnissa. Arvo 0 tarkoittaa rajatonta.",
|
||||
"rate_limit_subnet_len_ipv4": "IPv4-osoitteiden aliverkon etuliitteen pituus",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Aliverkon etuliitteen pituus IPv4-osoitteille, joita käytetään nopeuden rajoittamiseen. Oletusarvo on 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "IPv4-aliverkon etuliitteen pituuden tulee olla 0–32",
|
||||
"rate_limit_subnet_len_ipv6": "IPv6-osoitteiden aliverkon etuliitteen pituus",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Aliverkon etuliitteen pituus IPv6-osoitteille, joita käytetään nopeuden rajoittamiseen. Oletusarvo on 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "IPv6-aliverkon etuliitteen pituuden tulee olla 0–128",
|
||||
"form_enter_rate_limit_subnet_len": "Anna aliverkon etuliitteen pituus nopeuden rajoittamista varten",
|
||||
"rate_limit_whitelist": "Nopeutta rajoittava sallittu luettelo",
|
||||
"rate_limit_whitelist_desc": "IP-osoitteet, jotka eivät kuulu nopeusrajoituksen piiriin",
|
||||
"rate_limit_whitelist_placeholder": "Syötä yksi IP-osoite per rivi",
|
||||
"blocking_ipv4_desc": "Estettyyn A-pyyntöön palautettava IP-osoite",
|
||||
"blocking_ipv6_desc": "Estettyyn AAAA-pyyntöön palautettava IP-osoite",
|
||||
"blocking_mode_default": "Oletus: Vastaa IP-nollaosoitteella (0.0.0.0 korvaa A; :: korvaa AAAA) kun estetään mainoseston säännöllä; vastaa säännön määrittämällä IP-osoitteella kun estetään /etc/hosts-tyyppisellä säännöllä",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Paramètres du client",
|
||||
"example_upstream_reserved": "un amont <0>pour des domaines spécifiques</0> ;",
|
||||
"example_multiple_upstreams_reserved": "plusieurs amonts <0>pour des domaines spécifiques</0> ;",
|
||||
"example_upstream_comment": " un commentaire.",
|
||||
"upstream_parallel": "Utilisez des requêtes parallèles pour accélérer la résolution en requêtant simultanément tous les serveurs en amont.",
|
||||
"parallel_requests": "Requêtes en parallèle",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Tentative de malware/hameçonnage bloquée",
|
||||
"stats_adult": "Sites à contenu adulte bloqués",
|
||||
"stats_query_domain": "Domaines les plus recherchés",
|
||||
"for_last_24_hours": "pendant les dernières 24 heures",
|
||||
"for_last_hours": "pendant la dernière {{count}} heure",
|
||||
"for_last_hours_plural": "pendant les dernières {{count}} heures",
|
||||
"for_last_days": "pour les {{count}} derniers jours",
|
||||
"for_last_days_plural": "pour les {{count}} derniers jours",
|
||||
"stats_disabled": "Les statistiques ont été désactivées. Vous pouvez l'activer à partir de la <0>page des paramètres</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Aucune donnée en amont trouvée",
|
||||
"number_of_dns_query_days": "Le nombre de requêtes DNS traitées pour les {{count}} derniers jours",
|
||||
"number_of_dns_query_days_plural": "Le nombre de requêtes DNS traitées ces {{count}} derniers jours",
|
||||
"number_of_dns_query_24_hours": "Le nombre de requêtes DNS traitées au cours des 24 dernières heures",
|
||||
"number_of_dns_query_hours": "Le nombre de requêtes DNS traitées pendant la dernière {{count}} heure",
|
||||
"number_of_dns_query_hours_plural": "Le nombre de requêtes DNS traitées pendant les dernières {{count}} heures",
|
||||
"number_of_dns_query_blocked_24_hours": "Le nombre de requêtes DNS bloquées par les filtres adblock et les listes de blocage des hôtes",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Le nombre de requêtes DNS bloquées par le module Sécurité de navigation d'AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Le nombre de sites à contenu adulte bloqués",
|
||||
"enforced_save_search": "Recherche sécurisée forcée",
|
||||
"number_of_dns_query_to_safe_search": "Le nombre de requêtes DNS faites avec la Recherche securisée",
|
||||
"average_processing_time": "Temps moyen de traitement",
|
||||
"processing_time": "Délai de traitement",
|
||||
"average_upstream_response_time": "Temps de réponse moyen en amont",
|
||||
"response_time": "Temps de réponse",
|
||||
"average_processing_time_hint": "Temps moyen (en millisecondes) de traitement d'une requête DNS",
|
||||
"block_domain_use_filters_and_hosts": "Bloquez les domaines à l'aide des filtres et fichiers hosts",
|
||||
"filters_block_toggle_hint": "Vous pouvez configurer les règles de filtrage dans les paramètres des <a>Filtres</a>.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"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 qu’un seul client est autorisé à faire. Le réglage 0 fait illimité.",
|
||||
"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",
|
||||
"blocking_mode_default": "Par défaut : Répondre avec adresse IP zéro (0.0.0.0 pour A ; :: pour AAAA) lorsque bloqué par la règle de style Adblock ; répondre avec l’adresse IP spécifiée dans la règle lorsque bloquée par la règle du style /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Postavke klijenta",
|
||||
"example_upstream_reserved": "upstream <0>za određene domene</0>;",
|
||||
"example_multiple_upstreams_reserved": "višestruke upstream poslužitelje <0>za određene domene</0>;",
|
||||
"example_upstream_comment": "komentar.",
|
||||
"upstream_parallel": "Koristi paralelne upite kako bi ubrzali rješavanje istovremenim ispitavanjem svih upstream poslužitelja.",
|
||||
"parallel_requests": "Paralelni zahtjevi",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokiran zločudni program/krađe identiteta",
|
||||
"stats_adult": "Blokirane web stranice za odrasle",
|
||||
"stats_query_domain": "Top tražene domene",
|
||||
"for_last_24_hours": "u zadnja 24 sata",
|
||||
"for_last_hours": "za posljednji {{count}} sat",
|
||||
"for_last_hours_plural": "za posljednjih {{count}} sati",
|
||||
"for_last_days": "zadnjih {{count}} dana",
|
||||
"for_last_days_plural": "zadnjih {{count}} dana",
|
||||
"stats_disabled": "Statistika je onemogućena. Možete ga uključiti sa <0>stranice s postavkama</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nema podataka o upstream poslužiteljima",
|
||||
"number_of_dns_query_days": "Broj DNS upita obrađenih u posljednja {{count}} dan",
|
||||
"number_of_dns_query_days_plural": "Broj DNS upita obrađenih u posljednja {{count}} dana",
|
||||
"number_of_dns_query_24_hours": "Broj DNS upita obrađenih u posljednja 24 sata",
|
||||
"number_of_dns_query_hours": "Broj DNS upita obrađenih za posljednji {{count}} sat",
|
||||
"number_of_dns_query_hours_plural": "Broj DNS upita obrađenih za posljednjih {{count}} sati",
|
||||
"number_of_dns_query_blocked_24_hours": "Broj DNS zahtjeva koji blokiraju filtri za blokiranje oglasa i popisi blokova hostova",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Broj DNS zahtjeva koje je blokirao modul AdGuard zaštita pregledavanja",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Broj blokiranih stranica s sadržajem za odrasle",
|
||||
"enforced_save_search": "Omogućeno sigurno pretraživanje",
|
||||
"number_of_dns_query_to_safe_search": "Broj DNS zahtjeva prema pretraživačima za koje je omogućeno Sigurno pretraživanje",
|
||||
"average_processing_time": "Prosječno vrijeme obrade",
|
||||
"processing_time": "Vrijeme obrade",
|
||||
"average_upstream_response_time": "Prosječno vrijeme odziva upstream poslužitelja",
|
||||
"response_time": "Vrijeme odziva",
|
||||
"average_processing_time_hint": "Prosječno vrijeme u milisekundama za obradu DNS zahtjeva",
|
||||
"block_domain_use_filters_and_hosts": "Blokiraj domene koristeći filtre ili hosts datoteke",
|
||||
"filters_block_toggle_hint": "Pravila blokiranja možete postaviti u postavkama <a>filtara</a>.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"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_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",
|
||||
"blocking_mode_default": "Zadano: Odgovori s nultom IP adresom (0.0.0.0 za A; :: za AAAA) kada ga blokira Adblock slično pravilo; odgovorite s IP adresom definiranom u pravilu kada je blokirano od /etc/hosts sličnog pravila",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Kliens beállítások",
|
||||
"example_upstream_reserved": "Megadhat egy DNS kiszolgálót <0>egy adott domainhez vagy domainekhez</0>",
|
||||
"example_multiple_upstreams_reserved": "több upstream szerver <0>adott domainekhez</0>;",
|
||||
"example_upstream_comment": "egy megjegyzés.",
|
||||
"upstream_parallel": "Használjon párhuzamos lekéréseket a domainek feloldásának felgyorsításához az összes upstream kiszolgálóra való egyidejű lekérdezéssel.",
|
||||
"parallel_requests": "Párhuzamos lekérések",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokkolt kártevő/adathalászat",
|
||||
"stats_adult": "Blokkolt felnőtt tartalom",
|
||||
"stats_query_domain": "Leglátogatottabb domainek",
|
||||
"for_last_24_hours": "az utóbbi 24 órában",
|
||||
"for_last_hours": "az utolsó {{count}} órában",
|
||||
"for_last_hours_plural": "az utolsó {{count}} órában",
|
||||
"for_last_days": "az utóbbi {{count}} napban",
|
||||
"for_last_days_plural": "az utóbbi {{count}} napban",
|
||||
"stats_disabled": "Ezek a statisztikák ki lettek kapcsolva. Be tudja kapcsolni őket a <0>beállítások oldalon</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nem található upstream szerver adat",
|
||||
"number_of_dns_query_days": "Lekérdezések száma az utolsó {{count}} napban",
|
||||
"number_of_dns_query_days_plural": "Feldolgozott DNS lekérdezések száma az utolsó {{count}} napban",
|
||||
"number_of_dns_query_24_hours": "Az elmúlt 24 órában feldolgozott DNS lekérdezések száma",
|
||||
"number_of_dns_query_hours": "Feldolgozott DNS lekérdezések száma az utolsó {{count}} órában",
|
||||
"number_of_dns_query_hours_plural": "Feldolgozott DNS lekérdezések száma az utolsó {{count}} órában",
|
||||
"number_of_dns_query_blocked_24_hours": "A hirdetésblokkoló szűrők és a hosztfájlok által letiltott DNS kérések száma",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Az AdGuard böngészési biztonság modulja által letiltott DNS kérések száma",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Blokkolt felnőtt tartalmak száma",
|
||||
"enforced_save_search": "Kényszerített biztonságos keresés",
|
||||
"number_of_dns_query_to_safe_search": "A biztonságos keresésre kényszerített DNS lekérdezések száma",
|
||||
"average_processing_time": "Átlagos feldolgozási idő",
|
||||
"processing_time": "Feldolgozási idő",
|
||||
"average_upstream_response_time": "Átlagos upstream válaszidő",
|
||||
"response_time": "Válaszidő",
|
||||
"average_processing_time_hint": "A DNS lekérdezések feldolgozásához szükséges átlagos idő milliszekundumban",
|
||||
"block_domain_use_filters_and_hosts": "Domainek blokkolása szűrők és hosztfájlok használatával",
|
||||
"filters_block_toggle_hint": "A <a> szűrőbeállításoknál</a> megadhatja a blokkolási szabályokat.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Használjon egyéni IP-címet az EDNS-hez",
|
||||
"edns_use_custom_ip_desc": "Engedélyezze az egyéni IP-cím használatát az EDNS-hez",
|
||||
"rate_limit_desc": "Maximálisan hány kérést küldhet egy kliens másodpercenkén. Ha 0-ra állítja, akkor nincs korlátozás.",
|
||||
"rate_limit_subnet_len_ipv4": "Az IPv4-címek alhálózati előtagjának hossza",
|
||||
"rate_limit_subnet_len_ipv4_desc": "A sebességkorlátozáshoz használt IPv4-címek alhálózati előtagjának hossza. Az alapértelmezett érték 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Az IPv4 alhálózati előtag hosszának 0 és 32 között kell lennie",
|
||||
"rate_limit_subnet_len_ipv6": "Az IPv6-címek alhálózati előtagjának hossza",
|
||||
"rate_limit_subnet_len_ipv6_desc": "A sebességkorlátozáshoz használt IPv6-címek alhálózati előtagjának hossza. Az alapértelmezett érték 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Az IPv6 alhálózati előtag hosszának 0 és 128 között kell lennie",
|
||||
"form_enter_rate_limit_subnet_len": "Adja meg az alhálózati előtag hosszát a sebességkorlátozáshoz",
|
||||
"rate_limit_whitelist": "Sebességkorlátozó engedélyezési lista",
|
||||
"rate_limit_whitelist_desc": "A sebességkorlátozásból kizárt IP-címek",
|
||||
"rate_limit_whitelist_placeholder": "Adjon meg egy IP-címet soronként",
|
||||
"blocking_ipv4_desc": "A blokkolt A kéréshez visszaadandó IP-cím",
|
||||
"blocking_ipv6_desc": "A blokkolt AAAA kéréshez visszaadandó IP-cím",
|
||||
"blocking_mode_default": "Alapértelmezés: Válaszoljon nulla IP-címmel (vagyis 0.0.0.0 az A-hoz, :: pedig az AAAA-hoz), amikor a blokkolás egy adblock-stílusú szabállyal történik; illetve válaszoljon egy, a szabály által meghatározott IP címmel, amikor a blokkolás egy /etc/hosts stílusú szabállyal történik",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Pengaturan klien",
|
||||
"example_upstream_reserved": "upstream <0>untuk domain spesifik</0>;",
|
||||
"example_multiple_upstreams_reserved": "beberapa server upstream <0>untuk domain spesifik</0>;",
|
||||
"example_upstream_comment": "komentar.",
|
||||
"upstream_parallel": "Gunakan kueri paralel untuk mempercepat resoluasi dengan menanyakan semua server upstream secara bersamaan",
|
||||
"parallel_requests": "Permintaan paralel",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Malware/phishing diblokir",
|
||||
"stats_adult": "Situs dewasa diblokir",
|
||||
"stats_query_domain": "Kueri domain teratas",
|
||||
"for_last_24_hours": "untuk 24 jam terakhir",
|
||||
"for_last_hours": "selama {{count}} jam terakhir",
|
||||
"for_last_hours_plural": "selama {{count}} jam terakhir",
|
||||
"for_last_days": "untuk {{count}} hari terakhir",
|
||||
"for_last_days_plural": "selama {{count}} hari terakhir",
|
||||
"stats_disabled": "Statistik telah dinonaktifkan. Anda dapat mengaktifkannya dari <0>halaman setelan</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Tidak ada data server upstream yang ditemukan",
|
||||
"number_of_dns_query_days": "Jumlah kueri DNS diproses selama {{value}} hari terakhir",
|
||||
"number_of_dns_query_days_plural": "Jumlah kueri DNS yang diproses selama {{count}} hari terakhir",
|
||||
"number_of_dns_query_24_hours": "Jumlah kueri DNS diproses selama 24 jam terakhir",
|
||||
"number_of_dns_query_hours": "Jumlah kueri DNS diproses selama {{{count}} jam terakhir",
|
||||
"number_of_dns_query_hours_plural": "Jumlah kueri DNS diproses selama {{count}} jam terakhir",
|
||||
"number_of_dns_query_blocked_24_hours": "Julah DNS diblokir oleh penyaring adblock dan daftar blokir hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Jumlah perminataan DNS diblokir oleh modul Kemanan Penjelajahan AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Jumlah website dewasa diblokir",
|
||||
"enforced_save_search": "Paksa pencarian aman",
|
||||
"number_of_dns_query_to_safe_search": "Jumlah perminataan DNS ke mesin pencari yang dipaksa Pencarian Aman",
|
||||
"average_processing_time": "Rata-rata waktu pemrosesan",
|
||||
"processing_time": "Waktu pemrosesan",
|
||||
"average_upstream_response_time": "Waktu respons server upstream rata-rata",
|
||||
"response_time": "Waktu respons",
|
||||
"average_processing_time_hint": "Rata-rata waktu dalam milidetik untuk pemrosesan sebuah permintaan DNS",
|
||||
"block_domain_use_filters_and_hosts": "Blokir domain menggunakan filter dan file hosts",
|
||||
"filters_block_toggle_hint": "Anda dapat menyiapkan aturan pemblokiran di pengaturan <a>Penyaringan</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Gunakan IP khusus untuk EDNS",
|
||||
"edns_use_custom_ip_desc": "Izinkan untuk menggunakan IP kustom untuk EDNS",
|
||||
"rate_limit_desc": "Jumlah permintaan per detik yang diperbolehkan untuk satu klien. Atur ke 0 untuk tidak terbatas.",
|
||||
"rate_limit_subnet_len_ipv4": "Panjang awalan subnet untuk alamat IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Panjang awalan subnet untuk alamat IPv4 yang digunakan untuk pembatasan kecepatan. Standarnya adalah 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Panjang awalan subnet IPv4 harus antara 0 dan 32",
|
||||
"rate_limit_subnet_len_ipv6": "Panjang awalan subnet untuk alamat IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Panjang awalan subnet untuk alamat IPv6 yang digunakan untuk pembatasan kecepatan. Standarnya adalah 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Panjang awalan subnet IPv6 harus antara 0 dan 128",
|
||||
"form_enter_rate_limit_subnet_len": "Masukkan panjang awalan subnet untuk pembatasan kecepatan",
|
||||
"rate_limit_whitelist": "Daftar pembatasan tarif yang diizinkan",
|
||||
"rate_limit_whitelist_desc": "Alamat IP dikecualikan dari pembatasan tarif",
|
||||
"rate_limit_whitelist_placeholder": "Masukkan satu alamat IP per baris",
|
||||
"blocking_ipv4_desc": "Alamat IP akan dikembalikan untuk permintaan A yang diblokir",
|
||||
"blocking_ipv6_desc": "Alamat IP akan dipulihkan untuk permintaan AAAA yang diblokir",
|
||||
"blocking_mode_default": "Default: Tanggapi dengan alamat IP nol (0.0.0.0 untuk A; :: untuk AAAA) saat diblokir oleh aturan gaya Adblock; tanggapi dengan alamat IP yang ditentukan dalam aturan ketika diblokir oleh aturan gaya host /etc/",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Impostazioni client",
|
||||
"example_upstream_reserved": "un upstream <0>per specifici domini</0>;",
|
||||
"example_multiple_upstreams_reserved": "upstream multipli <0>per domini specifici</0>;",
|
||||
"example_upstream_comment": "un commento.",
|
||||
"upstream_parallel": "Utilizza richieste parallele per accelerare la risoluzione interrogando simultaneamente tutti i server upstream.",
|
||||
"parallel_requests": "Richieste parallele",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Malware/phishing bloccati",
|
||||
"stats_adult": "Siti per adulti bloccati",
|
||||
"stats_query_domain": "Domini maggiormente richiesti",
|
||||
"for_last_24_hours": "nelle ultime 24 ore",
|
||||
"for_last_hours": "per l'ultima {{count}} ora",
|
||||
"for_last_hours_plural": "per le ultime {{count}} ore",
|
||||
"for_last_days": "per gli ultimi {{count}} giorni",
|
||||
"for_last_days_plural": "per gli ultimi {{count}} giorni",
|
||||
"stats_disabled": "Le statistiche sono state disattivate. Puoi attivarle dalla <0>pagina delle impostazioni</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nessun dato upstream trovato",
|
||||
"number_of_dns_query_days": "Numero di richieste DNS elaborate negli ultimi {{count}} giorni",
|
||||
"number_of_dns_query_days_plural": "Numero di richieste DNS elaborate negli ultimi {{count}} giorni",
|
||||
"number_of_dns_query_24_hours": "Numero di richieste DNS elaborate nelle ultime 24 ore",
|
||||
"number_of_dns_query_hours": "Numero di richieste DNS processate nell'ultima {{count}} ora",
|
||||
"number_of_dns_query_hours_plural": "Numero di richieste DNS processate nelle ultime {{count}} ore",
|
||||
"number_of_dns_query_blocked_24_hours": "Numero di richieste DNS bloccate dai filtri per annunci e dagli elenchi di blocco host",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Numero di richieste DNS bloccate dal modulo sicurezza di navigazione di AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Numero di siti web per adulti bloccati",
|
||||
"enforced_save_search": "Ricerca sicura forzata",
|
||||
"number_of_dns_query_to_safe_search": "Numero di richieste DNS dai motori di ricerca per i quali la Ricerca Sicura è stata forzata",
|
||||
"average_processing_time": "Tempo di elaborazione medio",
|
||||
"processing_time": "Tempo di elaborazione",
|
||||
"average_upstream_response_time": "Tempo medio di risposta upstream",
|
||||
"response_time": "Tempo di risposta",
|
||||
"average_processing_time_hint": "Tempo medio in millisecondi per elaborare una richiesta DNS",
|
||||
"block_domain_use_filters_and_hosts": "Blocca domini utilizzando filtri e file hosts",
|
||||
"filters_block_toggle_hint": "Puoi impostare le regole di blocco nelle impostazioni dei <a>Filtri</a>.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"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_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",
|
||||
"blocking_mode_default": "Risponde con un indirizzo IP pari a zero (0.0.0.0 per A; :: per AAAA) quando bloccato da una regola in stile Blocca-annunci; risponde con l'indirizzo IP specificato nella regola quando bloccato da una regola in stile /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "クライアント設定",
|
||||
"example_upstream_reserved": "<0>特定のドメイン</0>に対してDNSアップストリームを指定できます。",
|
||||
"example_multiple_upstreams_reserved": "<0>特定ドメイン</0>のための複数のアップストリームサーバー;",
|
||||
"example_upstream_comment": "コメントを追加できます。",
|
||||
"upstream_parallel": "並列リクエストを使用する(同時にすべてのアップストリームサーバーに処理要求することで解決スピードが向上)",
|
||||
"parallel_requests": "並列リクエスト",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "ブロックされたマルウェア/フィッシング",
|
||||
"stats_adult": "ブロックされたアダルトウェブサイト",
|
||||
"stats_query_domain": "最も問合せされたドメイン",
|
||||
"for_last_24_hours": "過去24時間以内",
|
||||
"for_last_hours": "過去{{count}}時間",
|
||||
"for_last_hours_plural": "過去{{count}}時間",
|
||||
"for_last_days": "過去{{count}}日間以内",
|
||||
"for_last_days_plural": "過去{{count}}日間以内",
|
||||
"stats_disabled": "統計は無効化されています。<0>設定ページ</0>でオンにすることができます。",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "アップストリームのデータが見つかりません",
|
||||
"number_of_dns_query_days": "過去{{count}}日間に処理されたDNSクエリの数",
|
||||
"number_of_dns_query_days_plural": "過去{{count}}日間に処理されたDNSクエリの数",
|
||||
"number_of_dns_query_24_hours": "過去24時間に処理されたDNSクエリの数",
|
||||
"number_of_dns_query_hours": "過去{{count}}時間に処理されたDNSクエリの数",
|
||||
"number_of_dns_query_hours_plural": "過去{{count}}時間に処理されたDNSクエリの数",
|
||||
"number_of_dns_query_blocked_24_hours": "広告ブロックフィルタとhostsブロックリストによってブロックされたDNSリクエストの数",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "AdGuardブラウジングセキュリティモジュールによってブロックされたDNSリクエストの数",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "ブロックされたアダルトウェブサイトの数",
|
||||
"enforced_save_search": "強制されたセーフサーチ",
|
||||
"number_of_dns_query_to_safe_search": "セーフサーチが強制適用された検索エンジンへのDNSリクエストの数",
|
||||
"average_processing_time": "平均処理時間",
|
||||
"processing_time": "処理時間",
|
||||
"average_upstream_response_time": "アップストリームの平均応答時間",
|
||||
"response_time": "応答時間",
|
||||
"average_processing_time_hint": "DNSリクエストの処理にかかる平均時間(ミリ秒単位)",
|
||||
"block_domain_use_filters_and_hosts": "フィルタとhostsファイルを使用してドメインをブロックする",
|
||||
"filters_block_toggle_hint": "<a>フィルタ</a>の設定でブロックするルールを設定することができます。",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "EDNSにカスタムIPを使用する",
|
||||
"edns_use_custom_ip_desc": "EDNS に対してカスタム IP の使用を許可します。",
|
||||
"rate_limit_desc": "一つのクライアントに対して許可される1秒あたりのリクエスト数(「0」に設定すると、制限なしになります)",
|
||||
"rate_limit_subnet_len_ipv4": "IPv4 アドレスのサブネットプレフィックス長",
|
||||
"rate_limit_subnet_len_ipv4_desc": "rate limiting(レート制限)に使用される IPv4 アドレスのサブネットプレフィックス長です。デフォルト値は 24 です。",
|
||||
"rate_limit_subnet_len_ipv4_error": "IPv4 サブネットプレフィックス長は0〜32の範囲内である必要があります。",
|
||||
"rate_limit_subnet_len_ipv6": "IPv6 アドレスのサブネットプレフィックス長",
|
||||
"rate_limit_subnet_len_ipv6_desc": "rate limiting(レート制限)に使用される IPv6 アドレスのサブネットプレフィックス長です。デフォルト値は 56 です。",
|
||||
"rate_limit_subnet_len_ipv6_error": "IPv6 サブネットのプレフィックス長は0〜128の範囲内である必要があります。",
|
||||
"form_enter_rate_limit_subnet_len": "rate limiting(レート制限)のためのサブネットプレフィックス長を入力してください",
|
||||
"rate_limit_whitelist": "rate limiting(レート制限)の許可リスト",
|
||||
"rate_limit_whitelist_desc": "rate limiting(レート制限)の対象から外すIPアドレスを指定できます。",
|
||||
"rate_limit_whitelist_placeholder": "IPアドレスを1行に1つずづ入力してください。",
|
||||
"blocking_ipv4_desc": "ブロックされたAリクエストに対して応答されるIPアドレス",
|
||||
"blocking_ipv6_desc": "ブロックされたAAAAリクエストに対して応答されるIPアドレス",
|
||||
"blocking_mode_default": "デフォルト:Adblock系ルールによってブロックされると、ゼロIPアドレス(Aに対しては「0.0.0.0」、AAAAに対しては「::」)で応答します。/etc/hosts系ルールによってブロックされると、ルールにて指定されているIPアドレスで応答します。",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "클라이언트 설정",
|
||||
"example_upstream_reserved": "<0>특정 도메인에 대한</0> 업스트림;",
|
||||
"example_multiple_upstreams_reserved": "<0>특정 도메인</0>에 대한 여러 업스트림",
|
||||
"example_upstream_comment": "댓글.",
|
||||
"upstream_parallel": "쿼리 처리 속도를 높이려면 모든 업스트림 서버에서 동시에 병렬 쿼리를 사용해주세요.",
|
||||
"parallel_requests": "병렬 처리 요청",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "차단된 멀웨어/피싱",
|
||||
"stats_adult": "차단된 성인 웹사이트",
|
||||
"stats_query_domain": "쿼리 도메인",
|
||||
"for_last_24_hours": "지난 24시간 동안",
|
||||
"for_last_hours": "마지막 {{count}} 시간",
|
||||
"for_last_hours_plural": "마지막 {{count}} 시간의 기록",
|
||||
"for_last_days": "마지막 {{count}} 일",
|
||||
"for_last_days_plural": "마지막 {{count}} 일의 기록",
|
||||
"stats_disabled": "통계 기능이 꺼졌습니다. <0>설정 페이지</0>에서 켤 수 있습니다.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "업스트림 데이터 없음",
|
||||
"number_of_dns_query_days": "최근 {{count}}일 동안 처리된 DNS 쿼리의 수",
|
||||
"number_of_dns_query_days_plural": "최근 {{count}}일 동안 처리된 DNS 쿼리의 수",
|
||||
"number_of_dns_query_24_hours": "최근 24시간 동안 처리된 DNS 쿼리의 수",
|
||||
"number_of_dns_query_hours": "최근 {{count}}시간 동안 처리된 DNS 쿼리의 수",
|
||||
"number_of_dns_query_hours_plural": "최근 {{count}}시간 동안 처리된 DNS 쿼리의 수",
|
||||
"number_of_dns_query_blocked_24_hours": "광고 차단 필터 및 호스트 차단 목록에 의해 차단된 DNS 요청 수",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "AdGuard 브라우징 보안 모듈에 의해 차단된 DNS 요청 수",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "차단된 성인 웹 사이트의 수",
|
||||
"enforced_save_search": "세이프서치 강제",
|
||||
"number_of_dns_query_to_safe_search": "세이프서치가 적용된 검색 엔진에 대해 DNS 요청 수",
|
||||
"average_processing_time": "평균처리 시간",
|
||||
"processing_time": "처리 시간",
|
||||
"average_upstream_response_time": "평균 업스트림 응답 시간",
|
||||
"response_time": "응답 시간",
|
||||
"average_processing_time_hint": "DNS 요청 처리시 평균 시간(밀리초)",
|
||||
"block_domain_use_filters_and_hosts": "필터 및 호스트 파일을 사용하여 도메인 차단",
|
||||
"filters_block_toggle_hint": "차단규칙<a>필터</a>을 설정할 수 있습니다.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"edns_use_custom_ip": "EDNS에 사용자 지정 IP 사용",
|
||||
"edns_use_custom_ip_desc": "EDNS에 사용자 지정 IP 사용하도록 허용합니다.",
|
||||
"rate_limit_desc": "단일 클라이언트에서 허용 가능한 초 당 요청 생성 숫자 (0: 무제한)",
|
||||
"rate_limit_whitelist_placeholder": "한 줄에 하나씩 IP 주소를 입력하세요.",
|
||||
"blocking_ipv4_desc": "차단된 A 요청에 대해서 반환할 IP 주소",
|
||||
"blocking_ipv6_desc": "차단된 AAAA 요청에 대해서 반환할 IP 주소",
|
||||
"blocking_mode_default": "기본: Adblock 스타일 규칙에 의해 차단되면 제로 IP 주소(A는 0.0.0.0; AAAA는 ::)로 응답합니다; /etc/hosts 스타일 규칙에 의해 차단되면 규칙에 정의된 IP 주소로 응답합니다",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Cliëntinstellingen",
|
||||
"example_upstream_reserved": "een upstream <0>voor specifieke domeinen</0>;",
|
||||
"example_multiple_upstreams_reserved": "meerdere upstreams <0>voor specifieke domeinen</0>;",
|
||||
"example_upstream_comment": "een commentaar.",
|
||||
"upstream_parallel": "Parallelle verzoeken gebruiken om te versnellen door gelijktijdig verzoeken te sturen naar alle upstream servers.",
|
||||
"parallel_requests": "Parallelle verzoeken",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Geblokkeerde malware/phishing",
|
||||
"stats_adult": "Geblokkeerde 18+ websites",
|
||||
"stats_query_domain": "Meest bezochte domeinen",
|
||||
"for_last_24_hours": "van de laatste 24-uur",
|
||||
"for_last_hours": "voor het afgelopen {{count}} uur",
|
||||
"for_last_hours_plural": "voor de afgelopen {{count}} uren",
|
||||
"for_last_days": "sinds de laatste {{count}} dagen",
|
||||
"for_last_days_plural": "sinds de laatste {{count}} dagen",
|
||||
"stats_disabled": "Statistieken zijn uitgeschakeld. Je kunt ze inschakelen op de <0>instellingen pagina</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Geen upstreams-gegevens gevonden",
|
||||
"number_of_dns_query_days": "Aantal verwerkte DNS aanvragen van de laatste {{count}} dag",
|
||||
"number_of_dns_query_days_plural": "Aantal verwerkte DNS aanvragen van de laatste {{count}} dagen",
|
||||
"number_of_dns_query_24_hours": "Aantal verwerkte DNS aanvragen van de laatste 24 uur",
|
||||
"number_of_dns_query_hours": "Het aantal DNS-verzoeken dat het afgelopen {{count}} uur is verwerkt",
|
||||
"number_of_dns_query_hours_plural": "Het aantal DNS-verzoeken dat de afgelopen {{count}} uren is verwerkt",
|
||||
"number_of_dns_query_blocked_24_hours": "Aantal geblokkeerde DNS aanvragen door advertentie blokkering en hosts blokkeerlijsten",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Aantal geblokkeerde DNS aanvragen door AdGuard browsing beveiligingsmodule",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Aantal geblokkeerde 18+ websites",
|
||||
"enforced_save_search": "Geforceerd veilig zoeken",
|
||||
"number_of_dns_query_to_safe_search": "Aantal DNS aanvragen in zoekmachines dmv geforceerd veilig zoeken",
|
||||
"average_processing_time": "Gemiddelde procestijd",
|
||||
"processing_time": "Verwerkingstijd",
|
||||
"average_upstream_response_time": "Gemiddelde upstream responstijd",
|
||||
"response_time": "Responsetijd",
|
||||
"average_processing_time_hint": "Gemiddelde verwerkingstijd in milliseconden van een DNS aanvraag",
|
||||
"block_domain_use_filters_and_hosts": "Domeinen blokkeren d.m.v. filters en host-bestanden",
|
||||
"filters_block_toggle_hint": "Je kan blokkeringsregels toevoegen in de <a>Filters</a> instellingen.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Aangepast IP-adres gebruiken voor EDNS",
|
||||
"edns_use_custom_ip_desc": "Toestaan om aangepast IP-adres voor EDNS te gebruiken",
|
||||
"rate_limit_desc": "Het aantal verzoeken per seconde toegelaten per toestel. 0 betekent onbeperkt.",
|
||||
"rate_limit_subnet_len_ipv4": "Lengte subnetvoorvoegsel voor IPv4-adressen",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Lengte subnetvoorvoegsel voor IPv4-adressen die worden gebruikt voor snelheidsbeperking. De standaardwaarde is 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "De lengte van het IPv4-subnetvoorvoegsel moet tussen 0 en 32 liggen",
|
||||
"rate_limit_subnet_len_ipv6": "Lengte subnetvoorvoegsel voor IPv6-adressen",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Lengte subnetvoorvoegsel voor IPv6-adressen die worden gebruikt voor snelheidsbeperking. De standaardwaarde is 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "De lengte van het IPv6-subnetvoorvoegsel moet tussen 0 en 128 liggen",
|
||||
"form_enter_rate_limit_subnet_len": "Voer de lengte van het subnetvoorvoegsel in voor snelheidsbeperking",
|
||||
"rate_limit_whitelist": "Toelatingslijst voor snelheidsbeperking",
|
||||
"rate_limit_whitelist_desc": "IP-adressen uitgesloten van snelheidsbeperking",
|
||||
"rate_limit_whitelist_placeholder": "Voer één IP-adres per regel in",
|
||||
"blocking_ipv4_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek",
|
||||
"blocking_ipv6_desc": "IP-adres dat moet worden teruggegeven voor een geblokkeerd A-verzoek",
|
||||
"blocking_mode_default": "Standaard: Reageer met een nul IP adres (0.0.0.0 for A; :: voor AAAA) wanneer geblokkeerd door een Adblock-type regel; reageer met het IP-adres dat is opgegeven in de regel wanneer geblokkeerd door een /etc/hosts type regel",
|
||||
|
||||
@@ -128,7 +128,6 @@
|
||||
"enforced_save_search": "Påtvungede barnevennlige søk",
|
||||
"number_of_dns_query_to_safe_search": "Antall DNS-forespørsler til søkemotorer der \"Safe Search\" ble fremtvunget",
|
||||
"average_processing_time": "Gjennomsnittlig behandlingstid",
|
||||
"processing_time": "Behandlingstid",
|
||||
"average_processing_time_hint": "Gjennomsnittstid for behandling av DNS-forespørsler i millisekunder",
|
||||
"block_domain_use_filters_and_hosts": "Blokker domener ved hjelp av filtre, «hosts»-filer, og rå domener",
|
||||
"filters_block_toggle_hint": "Du kan sette opp blokkeringsoppføringer i <a>Filtre</a>-innstillingene.",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Ustawienia klienta",
|
||||
"example_upstream_reserved": "upstream <0>dla określonych domen</0>;",
|
||||
"example_multiple_upstreams_reserved": "wiele serwerów nadrzędnych <0>dla konkretnej domeny</0>;",
|
||||
"example_upstream_comment": "komentarz.",
|
||||
"upstream_parallel": "Użyj zapytań równoległych, aby przyspieszyć rozwiązywanie przez jednoczesne wysyłanie zapytań do wszystkich serwerów nadrzędnych.",
|
||||
"parallel_requests": "Równoległe żądania",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Zablokowane złośliwe oprogramowanie/phishing",
|
||||
"stats_adult": "Zablokowane witryny dla dorosłych",
|
||||
"stats_query_domain": "Najczęściej wyszukiwane domeny",
|
||||
"for_last_24_hours": "przez ostatnie 24 godziny",
|
||||
"for_last_hours": "w ciągu ostatniej {{count}} godziny",
|
||||
"for_last_hours_plural": "w ciągu ostatnich {{count}} godzin",
|
||||
"for_last_days": "za ostatni dzień {{count}}",
|
||||
"for_last_days_plural": "z ostatnich {{count}} dni",
|
||||
"stats_disabled": "Statystyki zostały wyłączone. Można je włączyć na <0>stronie ustawień</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Brak danych dotyczących serwerów nadrzędnych",
|
||||
"number_of_dns_query_days": "Liczba przetworzonych zapytań DNS w ciągu ostatnich {{count}} dni",
|
||||
"number_of_dns_query_days_plural": "Liczba przetworzonych zapytań DNS w ciągu ostatnich {{count}} dni",
|
||||
"number_of_dns_query_24_hours": "Liczba zapytań DNS przetworzonych w ciągu ostatnich 24 godzin",
|
||||
"number_of_dns_query_hours": "Liczba przetworzonych zapytań DNS w ciągu ostatniej {{count}} godziny",
|
||||
"number_of_dns_query_hours_plural": "Liczba przetworzonych zapytań DNS w ciągu ostatnich {{count}} godzin",
|
||||
"number_of_dns_query_blocked_24_hours": "Liczba żądań DNS zablokowanych przez filtry blokowania reklam i listy zablokowanych hostów",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Liczba żądań DNS zablokowanych przez moduł Bezpiecznego przeglądania AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Liczba zablokowanych witryn dla dorosłych",
|
||||
"enforced_save_search": "Wymuszone bezpieczne wyszukiwanie",
|
||||
"number_of_dns_query_to_safe_search": "Liczba żądań DNS kierowanych do wyszukiwarek, dla których wymuszono Bezpieczne wyszukiwanie",
|
||||
"average_processing_time": "Średni czas przetwarzania",
|
||||
"processing_time": "Czas przetwarzania",
|
||||
"average_upstream_response_time": "Średni czas odpowiedzi serwera nadrzędnego",
|
||||
"response_time": "Czas odpowiedzi",
|
||||
"average_processing_time_hint": "Średni czas przetwarzania żądania DNS liczony w milisekundach",
|
||||
"block_domain_use_filters_and_hosts": "Zablokuj domeny za pomocą filtrów i plików host",
|
||||
"filters_block_toggle_hint": "Możesz skonfigurować reguły blokowania w ustawieniach <a>Filtry</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Użyj niestandardowego adresu IP dla EDNS",
|
||||
"edns_use_custom_ip_desc": "Zezwól na użycie niestandardowego adresu IP dla EDNS",
|
||||
"rate_limit_desc": "Liczba żądań na sekundę dozwolona na klienta. Ustawienie wartości 0 oznacza brak ograniczeń.",
|
||||
"rate_limit_subnet_len_ipv4": "Długość maski podsieci dla adresów IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Długość maski podsieci dla adresów IPv4 używanych do ograniczania prędkości. Domyślnie jest to 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Długość maski podsieci IPv4 powinna wynosić od 0 do 32",
|
||||
"rate_limit_subnet_len_ipv6": "Długość prefiksu podsieci dla adresów IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Długość prefiksu podsieci dla adresów IPv6 używanych do ograniczania szybkości. Domyślnie jest to 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Długość prefiksu podsieci IPv6 powinna wynosić od 0 do 128",
|
||||
"form_enter_rate_limit_subnet_len": "Wprowadź długość prefiksu podsieci dla ograniczenia prędkości",
|
||||
"rate_limit_whitelist": "Lista zezwoleń ograniczających prędkość",
|
||||
"rate_limit_whitelist_desc": "Adresy IP wykluczone z ograniczania prędkości",
|
||||
"rate_limit_whitelist_placeholder": "Wprowadź po jednym adresie IP w każdym wierszu",
|
||||
"blocking_ipv4_desc": "Adres IP, który ma zostać zwrócony w przypadku zablokowanego żądania A",
|
||||
"blocking_ipv6_desc": "Adres IP, który ma zostać zwrócony w przypadku zablokowanego żądania AAAA",
|
||||
"blocking_mode_default": "Domyślna: Odpowiedz z zerowym adresem IP (0.0.0.0 dla A; :: dla AAAA) po zablokowaniu przez regułę Adblock; odpowiedź adresem IP wpisanym w regule, jeśli jest blokowany przez regułę w stylu /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Configurações do cliente",
|
||||
"example_upstream_reserved": "um DNS primário <0>para o domínios especificos</0>;",
|
||||
"example_multiple_upstreams_reserved": "múltiplos upstreams <0>para domínios específicos</0>;",
|
||||
"example_upstream_comment": "um comentário.",
|
||||
"upstream_parallel": "Usar consultas paralelas para acelerar a resolução consultando simultaneamente todos os servidores DNS primário",
|
||||
"parallel_requests": "Solicitações paralelas",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Bloqueado malware/phishing",
|
||||
"stats_adult": "Bloqueado sites adultos",
|
||||
"stats_query_domain": "Principais domínios consultados",
|
||||
"for_last_24_hours": "nas últimas 24 horas",
|
||||
"for_last_hours": "na última {{count}} hora",
|
||||
"for_last_hours_plural": "nas últimas {{count}} horas",
|
||||
"for_last_days": "nos últimos {{count}} dias",
|
||||
"for_last_days_plural": "nos últimos {{count}} dias",
|
||||
"stats_disabled": "As estatísticas foram desativadas. Você pode ligá-las através da <0>página de configurações</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nenhum dado de servidor DNS primário encontrado",
|
||||
"number_of_dns_query_days": "O número de consultas DNS processadas nos últimos {{count}} dias",
|
||||
"number_of_dns_query_days_plural": "Número de consultas DNS processadas nos últimos {{count}} dias",
|
||||
"number_of_dns_query_24_hours": "O número de consultas DNS processadas nas últimas 24 horas",
|
||||
"number_of_dns_query_hours": "Número de consultas DNS processadas durante a última {{count}} hora",
|
||||
"number_of_dns_query_hours_plural": "Número de consultas DNS processadas durante as últimas {{count}} horas",
|
||||
"number_of_dns_query_blocked_24_hours": "Várias solicitações DNS bloqueadas por filtros de bloqueio de anúncios e listas de bloqueio de hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Várias solicitações de DNS bloqueadas pelo módulo de segurança da navegação do AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "O número de sites adultos bloqueados",
|
||||
"enforced_save_search": "Forçar pesquisa segura",
|
||||
"number_of_dns_query_to_safe_search": "O número de solicitações de DNS para mecanismos de pesquisa para os quais a pesquisa segura foi aplicada",
|
||||
"average_processing_time": "Tempo médio de processamento",
|
||||
"processing_time": "Tempo de processamento",
|
||||
"average_upstream_response_time": "Tempo médio de resposta upstream",
|
||||
"response_time": "Tempo de resposta",
|
||||
"average_processing_time_hint": "Tempo médio em milissegundos no processamento de uma solicitação DNS",
|
||||
"block_domain_use_filters_and_hosts": "Bloquear domínios usando arquivos de filtros e hosts",
|
||||
"filters_block_toggle_hint": "Você pode configurar as regras de bloqueio nas configurações de <a>Filtros</a>.",
|
||||
@@ -299,13 +303,23 @@
|
||||
"download_mobileconfig_dot": "BAixar .mobileconfig para DNS-sobre-TLS",
|
||||
"download_mobileconfig": "Baixar arquivo de configuração",
|
||||
"plain_dns": "DNS simples",
|
||||
"form_enter_rate_limit": "Insira a taxa limite",
|
||||
"rate_limit": "Taxa limite",
|
||||
"form_enter_rate_limit": "Insira a velocidade limite",
|
||||
"rate_limit": "Velocidade limite",
|
||||
"edns_enable": "Ativar a sub-rede do cliente EDNS",
|
||||
"edns_cs_desc": "Adicione a opção de sub-rede de cliente EDNS (ECS) às solicitações de servidor DNS primário e registre os valores enviados pelos clientes no registro de consulta.",
|
||||
"edns_use_custom_ip": "Usar IP personalizado para EDNS",
|
||||
"edns_use_custom_ip_desc": "Permitir o uso de IP personalizado para EDNS",
|
||||
"rate_limit_desc": "O número de solicitações por segundo permitidas por cliente. Definir como 0 significa que não há limite.",
|
||||
"rate_limit_subnet_len_ipv4": "Comprimento do prefixo de sub-rede para endereços IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Comprimento do prefixo de sub-rede para endereços IPv4 usados para limitação de velocidade. O padrão é 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "O comprimento do prefixo da sub-rede IPv4 deve estar entre 0 e 32",
|
||||
"rate_limit_subnet_len_ipv6": "Comprimento do prefixo de sub-rede para endereços IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Comprimento do prefixo de sub-rede para endereços IPv6 usados para limitação de velocidade. O padrão é 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "O comprimento do prefixo da sub-rede IPv6 deve estar entre 0 e 128",
|
||||
"form_enter_rate_limit_subnet_len": "Insira o comprimento do prefixo da sub-rede para limitação de taxa",
|
||||
"rate_limit_whitelist": "Lista de permissões de limitação de velocidade",
|
||||
"rate_limit_whitelist_desc": "Endereços IP excluídos da limitação de velocidade",
|
||||
"rate_limit_whitelist_placeholder": "Insira um endereço IP por linha",
|
||||
"blocking_ipv4_desc": "Endereço de IP a ser retornado para uma solicitação bloqueada",
|
||||
"blocking_ipv6_desc": "Endereço de IP a ser retornado para uma solicitação AAAA bloqueada",
|
||||
"blocking_mode_default": "Padrão: Responder com zero endereço IP (0.0.0.0 para A; :: para AAAA) quando bloqueado pela regra de estilo Adblock; responde com o endereço IP especificado na regra quando bloqueado pela regra /etc/hosts-style",
|
||||
@@ -689,7 +703,7 @@
|
||||
"log_and_stats_section_label": "Registro de consultas e estatísticas",
|
||||
"ignore_query_log": "Ignorar este cliente no registo de consultas",
|
||||
"ignore_statistics": "Ignorar este cliente nas estatísticas",
|
||||
"schedule_services": "Pausa o bloqueio de serviço",
|
||||
"schedule_services": "Pausar bloqueio de serviço",
|
||||
"schedule_services_desc": "Configura o agendamento de pausa do filtro de bloqueio de serviço",
|
||||
"schedule_services_desc_client": "Configura o agendamento de pausa do filtro de bloqueio de serviço para este cliente",
|
||||
"schedule_desc": "Define períodos de inatividade para serviços bloqueados",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Definições do cliente",
|
||||
"example_upstream_reserved": "Podes especificar o DNS primário <0>para domínio(s) especifico(s)</0>",
|
||||
"example_multiple_upstreams_reserved": "múltiplos upstreams <0>para domínios específicos</0>;",
|
||||
"example_upstream_comment": "um comentário.",
|
||||
"upstream_parallel": "Usar consultas paralelas para acelerar a resolução consultando simultaneamente todos os servidores DNS",
|
||||
"parallel_requests": "Solicitações paralelas",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Malware/phishing bloqueados",
|
||||
"stats_adult": "Sítios adultos bloqueados",
|
||||
"stats_query_domain": "Principais domínios consultados",
|
||||
"for_last_24_hours": "nas últimas 24 horas",
|
||||
"for_last_hours": "na última {{count}} hora",
|
||||
"for_last_hours_plural": "nas últimas {{count}} horas",
|
||||
"for_last_days": "nos últimos {{count}} dias",
|
||||
"for_last_days_plural": "nos últimos {{count}} dias",
|
||||
"stats_disabled": "As estatísticas foram desativadas. Você pode ligá-las através da <0>página de definições</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nenhum dado de servidor DNS primário encontrado",
|
||||
"number_of_dns_query_days": "Número de consultas DNS processadas durante los últimos {{count}} días",
|
||||
"number_of_dns_query_days_plural": "Número de consultas DNS processadas durante os últimos {{count}} dias",
|
||||
"number_of_dns_query_24_hours": "O número de consultas DNS processadas nas últimas 24 horas",
|
||||
"number_of_dns_query_hours": "Número de consultas DNS processadas durante a última {{count}} hora",
|
||||
"number_of_dns_query_hours_plural": "Número de consultas DNS processadas durante as últimas {{count}} horas",
|
||||
"number_of_dns_query_blocked_24_hours": "Várias solicitações DNS bloqueadas por filtros de bloqueio de anúncios e listas de bloqueio de hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Várias solicitações de DNS bloqueadas pelo módulo de segurança da navegação do AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "O número de sítios adultos bloqueados",
|
||||
"enforced_save_search": "Forçar pesquisa segura",
|
||||
"number_of_dns_query_to_safe_search": "O número de solicitações de DNS para motores de busca para os quais a pesquisa segura foi aplicada",
|
||||
"average_processing_time": "Tempo médio de processamento",
|
||||
"processing_time": "Tempo de processamento",
|
||||
"average_upstream_response_time": "Tempo médio de resposta upstream",
|
||||
"response_time": "Tempo de resposta",
|
||||
"average_processing_time_hint": "Tempo médio em milissegundos no processamento de uma solicitação DNS",
|
||||
"block_domain_use_filters_and_hosts": "Bloquear domínios usando ficheiros de filtros e hosts",
|
||||
"filters_block_toggle_hint": "Pode configurar as regras de bloqueio nas configurações de <a>Filtros</a>.",
|
||||
@@ -299,13 +303,23 @@
|
||||
"download_mobileconfig_dot": "Transferir .mobileconfig para DNS-sobre-TLS",
|
||||
"download_mobileconfig": "Transferir ficheiro de configuração",
|
||||
"plain_dns": "DNS simples",
|
||||
"form_enter_rate_limit": "Insira o limite de taxa",
|
||||
"rate_limit": "Limite de taxa",
|
||||
"form_enter_rate_limit": "Insira o limite de velocidade",
|
||||
"rate_limit": "Limite de velocidade",
|
||||
"edns_enable": "Ativar a sub-rede do cliente EDNS",
|
||||
"edns_cs_desc": "Adicione a opção de sub-rede de cliente EDNS (ECS) às solicitações de servidor DNS primário e registre os valores enviados pelos clientes no registo de consulta.",
|
||||
"edns_use_custom_ip": "Usar IP personalizado para EDNS",
|
||||
"edns_use_custom_ip_desc": "Permitir a utilização de IP personalizado para EDNS",
|
||||
"rate_limit_desc": "O número de solicitações por segundo permitido por cliente. Configurando para 0 significa sem limite.",
|
||||
"rate_limit_subnet_len_ipv4": "Comprimento do prefixo de sub-rede para endereços IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Comprimento do prefixo de sub-rede para endereços IPv4 usados para limitação de velocidade. O padrão é 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "O comprimento do prefixo da sub-rede IPv4 deve estar entre 0 e 32",
|
||||
"rate_limit_subnet_len_ipv6": "Comprimento do prefixo de sub-rede para endereços IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Comprimento do prefixo de sub-rede para endereços IPv6 usados para limitação de velocidade. O padrão é 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "O comprimento do prefixo da sub-rede IPv6 deve situar-se entre 0 e 128",
|
||||
"form_enter_rate_limit_subnet_len": "Introduza o comprimento do prefixo da sub-rede para limitação da velocidade",
|
||||
"rate_limit_whitelist": "Lista de permissões de limitação de velocidade",
|
||||
"rate_limit_whitelist_desc": "Endereços IP excluídos da limitação de velocidade",
|
||||
"rate_limit_whitelist_placeholder": "Insira um endereço IP por linha",
|
||||
"blocking_ipv4_desc": "Endereço IP a ser devolvido para uma solicitação A bloqueada",
|
||||
"blocking_ipv6_desc": "Endereço IP a ser devolvido para uma solicitação AAAA bloqueada",
|
||||
"blocking_mode_default": "Predefinido: Responder com zero endereço IP (0.0.0.0 para A; :: para AAAA) quando bloqueado pela regra de estilo Adblock; responde com o endereço IP especificado na regra quando bloqueado pela regra /etc/hosts-style",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Setări client",
|
||||
"example_upstream_reserved": "un flux în amonte <0>pentru domenii specifice</0>;",
|
||||
"example_multiple_upstreams_reserved": "mai mulți servere în amonte <0>pentru domenii specifice</0>;",
|
||||
"example_upstream_comment": "un comentariu.",
|
||||
"upstream_parallel": "Folosiți interogări paralele pentru a accelera rezolvarea, interogând simultan toate serverele în amonte.",
|
||||
"parallel_requests": "Solicitări paralele",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Malware/phishing blocate",
|
||||
"stats_adult": "Site-uri cu conținut adult blocate",
|
||||
"stats_query_domain": "Domeniile cele mai căutate",
|
||||
"for_last_24_hours": "în ultimele 24 ore",
|
||||
"for_last_hours": "în ultima {{count}} oră",
|
||||
"for_last_hours_plural": "în ultimele {{count}} ore",
|
||||
"for_last_days": "în ultima {{count}} zi",
|
||||
"for_last_days_plural": "pentru ultimele {{count}} zile",
|
||||
"stats_disabled": "Statisticile au fost dezactivate. Puteți să le porniți din <0>pagina de setări</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nu există date despre serverele din amonte",
|
||||
"number_of_dns_query_days": "Numărul de interogări DNS procesate în ultima {{count}} zi",
|
||||
"number_of_dns_query_days_plural": "Numărul de interogări DNS procesate în ultimele {{count}} zile",
|
||||
"number_of_dns_query_24_hours": "Numărul de interogări DNS procesate în ultimele 24 de ore",
|
||||
"number_of_dns_query_hours": "Numărul de interogări DNS procesate în ultima {{count}} oră",
|
||||
"number_of_dns_query_hours_plural": "Numărul de interogări DNS procesate în ultimele {{count}} ore",
|
||||
"number_of_dns_query_blocked_24_hours": "Numărul de interogări DNS blocate de filtrele adblock și lista de blocări din hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Numărul de interogări DNS blocate de modulul de securitate de navigare AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Numărul de site-uri pentru adulți blocate",
|
||||
"enforced_save_search": "Căutare protejată întărită",
|
||||
"number_of_dns_query_to_safe_search": "Numărul de interogări DNS pe motoarele de căutare pentru care a fost impusă Căutarea Sigură",
|
||||
"average_processing_time": "Timpul mediu de procesare",
|
||||
"processing_time": "Timp de procesare",
|
||||
"average_upstream_response_time": "Timpul mediu de răspuns al serverului în amonte",
|
||||
"response_time": "Timp de răspuns",
|
||||
"average_processing_time_hint": "Timp mediu în milisecunde la procesarea unei cereri DNS",
|
||||
"block_domain_use_filters_and_hosts": "Blocați domenii folosind filtre și fișiere hosts",
|
||||
"filters_block_toggle_hint": "Puteți configura regulile de blocare în setările <a>Filtre</a>.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"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_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",
|
||||
"blocking_mode_default": "Implicit: Răspunde cu adresa IP (0.0.0.0 for A; :: pentru AAAA) când sunt blocate de regulă tip Adblock; răspunde cu adresa IP specificată în regulă când sunt blocate de regula tip /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Настройки клиентов",
|
||||
"example_upstream_reserved": "DNS-сервер <0>для конкретных доменов</0>;",
|
||||
"example_multiple_upstreams_reserved": "несколько DNS-серверов <0>для конкретных доменов</0>;",
|
||||
"example_upstream_comment": "комментарий.",
|
||||
"upstream_parallel": "Использовать параллельные запросы ко всем серверам одновременно для ускорения обработки запроса.",
|
||||
"parallel_requests": "Параллельные запросы",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Заблокированные вредоносные и фишинговые сайты",
|
||||
"stats_adult": "Заблокированные «взрослые» сайты",
|
||||
"stats_query_domain": "Часто запрашиваемые домены",
|
||||
"for_last_24_hours": "за 24 часа",
|
||||
"for_last_hours": "за последний {{count}} час",
|
||||
"for_last_hours_plural": "за последние {{count}} часов",
|
||||
"for_last_days": "за последний {{count}} день",
|
||||
"for_last_days_plural": "за последние {{count}} дней",
|
||||
"stats_disabled": "Статистика отключена. Вы можете включить её на <0>странице настроек</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Нет данных об upstream-серверах",
|
||||
"number_of_dns_query_days": "Количество DNS-запросов за последний {{count}} день",
|
||||
"number_of_dns_query_days_plural": "Количество DNS запросов, обработанных за последние {{count}} дней",
|
||||
"number_of_dns_query_24_hours": "Количество DNS-запросов за последние 24 часа",
|
||||
"number_of_dns_query_hours": "Количество DNS-запросов, обработанных за последний {{count}} час",
|
||||
"number_of_dns_query_hours_plural": "Количество DNS-запросов, обработанных за последние {{count}} часов",
|
||||
"number_of_dns_query_blocked_24_hours": "Количество DNS-запросов, заблокированных фильтрами и блок-списками",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Количество DNS-запросов, заблокированных модулем Антифишинга AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Количество заблокированных «сайтов для взрослых»",
|
||||
"enforced_save_search": "Применён безопасный поиск",
|
||||
"number_of_dns_query_to_safe_search": "Количество запросов DNS для поисковых систем, для которых был применён Безопасный поиск",
|
||||
"average_processing_time": "Среднее время обработки запроса",
|
||||
"processing_time": "Время обработки",
|
||||
"average_upstream_response_time": "Среднее время ответа upstream-сервера",
|
||||
"response_time": "Время ответа",
|
||||
"average_processing_time_hint": "Среднее время для обработки запроса DNS в миллисекундах",
|
||||
"block_domain_use_filters_and_hosts": "Блокировать домены с использованием фильтров и файлов hosts",
|
||||
"filters_block_toggle_hint": "Вы можете настроить правила блокировки в <a>«Фильтрах»</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Использовать указанный IP для EDNS",
|
||||
"edns_use_custom_ip_desc": "Разрешить использовать собственный IP для EDNS",
|
||||
"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-запроса",
|
||||
"blocking_mode_default": "Стандартный: Отвечает с нулевым IP-адресом, (0.0.0.0 для A; :: для AAAA) когда заблокировано правилом в стиле Adblock; отвечает с IP-адресом, указанным в правиле, когда заблокировано правилом в стиле файлов hosts",
|
||||
|
||||
@@ -122,7 +122,6 @@
|
||||
"enforced_save_search": "ආරක්ෂිත සෙවීම බලාත්මක කළ",
|
||||
"number_of_dns_query_to_safe_search": "ආරක්ෂිත සෙවීම බලාත්මක කළ සෙවුම් යන්ත්ර සඳහා ව.නා.ප. ඉල්ලීම් ගණන",
|
||||
"average_processing_time": "සාමාන්ය සැකසුම් කාලය",
|
||||
"processing_time": "සැකසුම් කාලය",
|
||||
"average_processing_time_hint": "ව.නා.ප. ඉල්ලීමක් සැකසීමේ සාමාන්ය කාලය මිලි තත්පර වලින්",
|
||||
"block_domain_use_filters_and_hosts": "පෙරහන් හා සත්කාරක ගොනු භාවිතයෙන් වසම් අවහිර කරන්න",
|
||||
"filters_block_toggle_hint": "ඔබට අවහිර කිරීමේ නීති <a>පෙරහන්</a> තුළ පිහිටුවිය හැකිය.",
|
||||
@@ -647,6 +646,20 @@
|
||||
"log_and_stats_section_label": "විමසුම් සටහන හා සංඛ්යාලේඛන",
|
||||
"ignore_query_log": "විමසුම් සටහනට මෙම අනුග්රාහකය යොදන්න එපා",
|
||||
"ignore_statistics": "සංඛ්යාලේඛනයට මෙම අනුග්රාහකය යොදන්න එපා",
|
||||
"schedule_invalid_select": "ආරම්භක වේලාව අවසන් වේලාවට කලින් විය යුතුය",
|
||||
"schedule_select_days": "දවස් තෝරන්න",
|
||||
"schedule_timezone": "වේලා කලාපයක් තෝරන්න",
|
||||
"schedule_current_timezone": "වත්මන් වේලා කලාපය: {{value}}",
|
||||
"schedule_time_all_day": "දවස පුරාම",
|
||||
"schedule_from": "සිට",
|
||||
"schedule_to": "දක්වා",
|
||||
"sunday": "ඉරිදා",
|
||||
"monday": "සඳුදා",
|
||||
"tuesday": "අඟහරුවාදා",
|
||||
"wednesday": "බදාදා",
|
||||
"thursday": "බ්රහස්පතින්දා",
|
||||
"friday": "සිකුරාදා",
|
||||
"saturday": "සෙනසුරාදා",
|
||||
"sunday_short": "ඉරිදා",
|
||||
"monday_short": "සඳුදා",
|
||||
"tuesday_short": "අඟහ",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Nastavenie klienta",
|
||||
"example_upstream_reserved": "upstream <0>pre konkrétne domény</0>;",
|
||||
"example_multiple_upstreams_reserved": "viaceré upstreamy pre <0>konkrétne domény</0>;",
|
||||
"example_upstream_comment": "komentár.",
|
||||
"upstream_parallel": "Používať paralelné dopyty na zrýchlenie súčasným dopytovaním všetkých upstream serverov súčasne.",
|
||||
"parallel_requests": "Paralelné dopyty",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokovaný škodlivý kód/pokus o podvod",
|
||||
"stats_adult": "Blokovaná stránka pre dospelých",
|
||||
"stats_query_domain": "Najčastejšie dopytované domény",
|
||||
"for_last_24_hours": "za posledných 24 hodín",
|
||||
"for_last_hours": "za poslednú {{count}} hodinu",
|
||||
"for_last_hours_plural": "za posledné {{count}} hodiny|za posledných {{count}} hodín",
|
||||
"for_last_days": "za posledný {{count}} deň",
|
||||
"for_last_days_plural": "za posledných {{count}} dní",
|
||||
"stats_disabled": "Štatistiky boli vypnuté. Môžete ich zapnúť na <0>stránke nastavení</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nenašli sa žiadne údaje o upstream serveroch",
|
||||
"number_of_dns_query_days": "Počet DNS dopytov spracovaných za posledný {{count}} deň",
|
||||
"number_of_dns_query_days_plural": "Počet DNS dopytov spracovaných za posledných {{count}} dní",
|
||||
"number_of_dns_query_24_hours": "Počet DNS dopytov spracovaných za posledných 24 hodín",
|
||||
"number_of_dns_query_hours": "Počet DNS dopytov spracovaných za poslednú {{count}} hodinu",
|
||||
"number_of_dns_query_hours_plural": "Počet DNS dopytov spracovaných za posledné {{count}} hodiny)|Počet DNS dopytov spracovaných za posledných {{count}} hodín",
|
||||
"number_of_dns_query_blocked_24_hours": "Počet DNS dopytov zablokovaných filtrami reklamy a zoznamami blokovaných hostov",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Počet DNS dopytov zablokovaných AdGuard modulom Bezpečné prehliadanie",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Počet zablokovaných stránok pre dospelých",
|
||||
"enforced_save_search": "Vynútené bezpečné vyhľadávanie",
|
||||
"number_of_dns_query_to_safe_search": "Počet DNS dopytov na vyhľadávače, pri ktorých bolo vynútené bezpečné vyhľadávanie",
|
||||
"average_processing_time": "Priemerný čas spracovania",
|
||||
"processing_time": "Doba spracovania",
|
||||
"average_upstream_response_time": "Priemerný čas odozvy upstreamu",
|
||||
"response_time": "Čas odozvy",
|
||||
"average_processing_time_hint": "Priemerný čas spracovania DNS dopytu v milisekundách",
|
||||
"block_domain_use_filters_and_hosts": "Blokovať domény pomocou filtrov a zoznamov adries",
|
||||
"filters_block_toggle_hint": "Pravidlá blokovania môžete nastaviť v nastaveniach <a>Filtre</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Použiť vlastnú IP adresu pre EDNS",
|
||||
"edns_use_custom_ip_desc": "Povoliť používanie vlastnej IP adresy pre EDNS",
|
||||
"rate_limit_desc": "Počet požiadaviek za sekundu, ktoré môže jeden klient vykonať. Nastavenie na hodnotu 0 znamená neobmedzene.",
|
||||
"rate_limit_subnet_len_ipv4": "Dĺžka prefixu podsiete pre adresy IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Dĺžka prefixu podsiete pre adresy IPv4 používané na obmedzenie rýchlosti. Predvolená hodnota je 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Dĺžka prefixu podsiete IPv4 musí byť od 0 do 32",
|
||||
"rate_limit_subnet_len_ipv6": "Dĺžka prefixu podsiete pre adresy IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Dĺžka prefixu podsiete pre adresy IPv6 používané na obmedzenie rýchlosti. Predvolená hodnota je 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Dĺžka prefixu podsiete IPv6 musí byť od 0 do 128",
|
||||
"form_enter_rate_limit_subnet_len": "Zadajte dĺžku prefixu podsiete pre obmedzenie rýchlosti",
|
||||
"rate_limit_whitelist": "Zoznam povolení obmedzujúcich rýchlosť",
|
||||
"rate_limit_whitelist_desc": "IP adresy vylúčené z obmedzenia rýchlosti",
|
||||
"rate_limit_whitelist_placeholder": "Na každý riadok zadajte IP adresu jedného servera",
|
||||
"blocking_ipv4_desc": "IP adresa, ktorá sa má vrátiť v prípade blokovanej žiadosti A",
|
||||
"blocking_ipv6_desc": "IP adresa, ktorá sa má vrátiť v prípade blokovanej žiadosti AAAA",
|
||||
"blocking_mode_default": "Predvolené: Odpovedať nulovou adresou IP (0,0.0.0 pre A; :: pre AAAA), keď je blokovaná pravidlom v štýle Adblock; odpovedať IP adresou uvedenou v pravidle, keď je blokovaná pravidlom v štýle /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Nastavitve odjemalca",
|
||||
"example_upstream_reserved": "gorvodni <0>za določene domene</0>;",
|
||||
"example_multiple_upstreams_reserved": "več gorvodnih <0>za določene domene</0>;",
|
||||
"example_upstream_comment": "komentar.",
|
||||
"upstream_parallel": "Uporabite vzporedne zahteve za pospešitev reševanja s hkratnim poizvedovanjem vseh gorvodnih strežnikov.",
|
||||
"parallel_requests": "Vzporedne zahteve",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Onemogočeno zlonamernih programov/lažnih predstavljanj",
|
||||
"stats_adult": "Onemogočeno spletnih strani za odrasle",
|
||||
"stats_query_domain": "Najbolj poizvedovane domene",
|
||||
"for_last_24_hours": "v zadnjih 24 urah",
|
||||
"for_last_hours": "za zadnjo {{count}} uro",
|
||||
"for_last_hours_plural": "za zadnjih {{count}} ur",
|
||||
"for_last_days": "zadnjega {{count}} dne",
|
||||
"for_last_days_plural": "zadnjih {{count}} dni",
|
||||
"stats_disabled": "Statistika je onemogočena. Vklopite ga lahko na <0>strani z nastavitvami</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Ni podatkov o gorvodnih strežnikih",
|
||||
"number_of_dns_query_days": "Število obdelanih poizvedb DNS v zadnjem {{count}} dnevu",
|
||||
"number_of_dns_query_days_plural": "Število obdelanih poizvedb DNS v zadnjih {{count}} dneh",
|
||||
"number_of_dns_query_24_hours": "Število obdelanih poizvedb DNS v zadnjih 24 urah",
|
||||
"number_of_dns_query_hours": "Število poizvedb DNS, obdelanih v zadnji {{count}} uri",
|
||||
"number_of_dns_query_hours_plural": "Število poizvedb DNS, obdelanih v zadnjih {{count}} urah",
|
||||
"number_of_dns_query_blocked_24_hours": "Število zahtev DNS, ki so jih onemogočili filtri za zaviranje oglasov in seznami nedovoljenih, gostiteljev",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Število zahtev DNS, ki jih je blokiral AdGuard zaščitni modul brskanja",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Število onemogočenih spletnih strani za odrasle",
|
||||
"enforced_save_search": "Prisilno varno iskanje",
|
||||
"number_of_dns_query_to_safe_search": "Število zahtev DNS za iskalnike, za katere je bilo uveljavljeno varno iskanje",
|
||||
"average_processing_time": "Povprečni čas obdelave",
|
||||
"processing_time": "Čas obdelave",
|
||||
"average_upstream_response_time": "Povprečni gorvodni odzivni čas",
|
||||
"response_time": "Odzivni čas",
|
||||
"average_processing_time_hint": "Povprečni čas v milisekundah pri obdelavi zahteve DNS",
|
||||
"block_domain_use_filters_and_hosts": "Onemogoči domene s filtri in gostiteljskimi datotekami",
|
||||
"filters_block_toggle_hint": "Pravila zaviranja lahko nastavite v nastavitvah <a>Filtri</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Uporabi IP po meri za EDNS",
|
||||
"edns_use_custom_ip_desc": "Dovoli uporabo naslova IP po meri za EDNS",
|
||||
"rate_limit_desc": "Dovoljeno število zahtev na sekundo na odjemalca. Nastavitev na 0 pomeni brez omejitve.",
|
||||
"rate_limit_subnet_len_ipv4": "Dolžina predpone podomrežja za naslove IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Dolžina predpone podomrežja za naslove IPv4, ki se uporabljajo za omejevanje hitrosti. Privzeto je 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Dolžina predpone podomrežja IPv4 mora biti med 0 in 32",
|
||||
"rate_limit_subnet_len_ipv6": "Dolžina predpone podomrežja za naslove IPv4",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Dolžina predpone podomrežja za naslove IPv6, ki se uporabljajo za omejevanje hitrosti. Privzeta vrednost je 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Dolžina podomrežne predpone IPv6 mora biti med 0 in 128",
|
||||
"form_enter_rate_limit_subnet_len": "Vnesite dolžino predpone podomrežja za omejitev hitrosti",
|
||||
"rate_limit_whitelist": "Seznam dovoljenih za omejevanje hitrosti",
|
||||
"rate_limit_whitelist_desc": "Naslovi IP so izključeni iz omejitve hitrosti",
|
||||
"rate_limit_whitelist_placeholder": "Vnesite en naslov IP na vrstico",
|
||||
"blocking_ipv4_desc": "IP naslov, ki mora biti vrnjen za onemogočeno zahtevo A",
|
||||
"blocking_ipv6_desc": "IP naslov, ki mora biti vrnjen za onemogočeno zahtevo AAAA",
|
||||
"blocking_mode_default": "Privzeto: odgovori z ničelnim naslovom IP (0.0.0.0 za A; :: za AAAA), ko je onemogočen s pravilom v slogu Adblocka; odgovor z naslovom IP, določenim v pravilu, ko je onemogočen s pravilom /etc/hosts",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Postavke klijenta",
|
||||
"example_upstream_reserved": "upstream <0>za određene domene</0>;",
|
||||
"example_multiple_upstreams_reserved": "nekoliko DNS servera <0>za određene domene</0>;",
|
||||
"example_upstream_comment": "komentar.",
|
||||
"upstream_parallel": "Koristite paralelne upite da biste ubrzali rešavanje tako što ćete istovremeno ispitati sve uzvodne servere.",
|
||||
"parallel_requests": "Paralelni zahtevi",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blokiraj štetan softver i fišing",
|
||||
"stats_adult": "Blokiraj sajtove za odrasle",
|
||||
"stats_query_domain": "Najčešće unošeni domeni",
|
||||
"for_last_24_hours": "u poslednja 24 časa",
|
||||
"for_last_hours": "u poslednjih {{count}} sat",
|
||||
"for_last_hours_plural": "u poslednjih {{count}} sati",
|
||||
"for_last_days": "u poslednjih {{count}} dana",
|
||||
"for_last_days_plural": "u poslednjih {{count}} dana",
|
||||
"stats_disabled": "Statistika je isključena. Možete ga uključiti sa stranice <0>sa postavkama</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Nema podataka o upstream serverima",
|
||||
"number_of_dns_query_days": "Broj obrađenih DNS unosa u poslednjih {{count}} dan",
|
||||
"number_of_dns_query_days_plural": "Broj obrađenih DNS unosa u poslednjih {{count}} dana",
|
||||
"number_of_dns_query_24_hours": "Broj obrađenih DNS unosa u poslednja 24 časa",
|
||||
"number_of_dns_query_hours": "Broj obrađenih DNS unosa u poslednji {{count}} sat",
|
||||
"number_of_dns_query_hours_plural": "Broj obrađenih DNS unosa u poslednjih {{count}} sati",
|
||||
"number_of_dns_query_blocked_24_hours": "Broj DNS zahteva blokiranih od filtera blokatora reklama i blok liste hostova",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Broj DNS zahteva blokiranih od AdGuard-ovog podprograma za bezbedno pregledanje",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Broj blokiranih sajtova za odrasle",
|
||||
"enforced_save_search": "Nametni sigurno pretraživanje",
|
||||
"number_of_dns_query_to_safe_search": "Broj DNS zahteva ka pretraživačima za koje je nametnuto sigurno pretraživanje",
|
||||
"average_processing_time": "Prosečno vreme obrade",
|
||||
"processing_time": "Vreme obrade",
|
||||
"average_upstream_response_time": "Prosečno vreme odziva upstream-servera",
|
||||
"response_time": "Vreme odziva",
|
||||
"average_processing_time_hint": "Prosečno vreme u milisekundama za obradu DNS zahteva",
|
||||
"block_domain_use_filters_and_hosts": "Blokiraj domene koristeći filtere i hosts datoteke",
|
||||
"filters_block_toggle_hint": "Možete postaviti pravila blokiranja u <a>Filters</a> postavkama.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Koristi prilagođeni IP za EDNS",
|
||||
"edns_use_custom_ip_desc": "Dozvoli korišćenje prilagođenog IP-a za EDNS",
|
||||
"rate_limit_desc": "Broj zahteva u sekundi dozvoljen po klijentu. Postavljanje na 0 znači da nema ograničenja.",
|
||||
"rate_limit_subnet_len_ipv4": "Dužina prefixa podmreže za IPv4 adrese",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Dužina prefixa podmreže za IPv4 adrese koje se koriste za ograničavanje brzine. Podrazumevano je 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Dužina prefixa IPv4 podmreže treba da bude između 0 i 32",
|
||||
"rate_limit_subnet_len_ipv6": "Dužina prefixa podmreže za IPv6 adrese",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Dužina prefixa podmreže za IPv6 adrese koje se koriste za ograničavanje brzine. Podrazumevano je 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Dužina prefixa IPv6 podmreže treba da bude između 0 i 128",
|
||||
"form_enter_rate_limit_subnet_len": "Unesite dužinu prefixa podmreže da biste ograničili brzinu",
|
||||
"rate_limit_whitelist": "Lista dozvoljenih lista za ograničavanje brzine",
|
||||
"rate_limit_whitelist_desc": "IP adrese koje nisu obuhvaćene ograničenjem brzine",
|
||||
"rate_limit_whitelist_placeholder": "Unesite jednu IP adresu servera po redu",
|
||||
"blocking_ipv4_desc": "IP adresa koja će biti vraćena za blokirane zahteve",
|
||||
"blocking_ipv6_desc": "IP adresa koja će biti vraćena za blokirane AAAA zahteve",
|
||||
"blocking_mode_default": "Podrazumevano: Odgovara sa REFUSED kada je blokirano od Adblock-style pravila; odgovara sa IP adresom koja je određena u pravilu kada je blokiran od /etc/hosts-style pravila",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{
|
||||
"client_settings": "Klientinställningar",
|
||||
"example_upstream_reserved": "uppström <0>för en specifik domän</0>;",
|
||||
"example_upstream_comment": "du kan ange en kommentar.",
|
||||
"example_multiple_upstreams_reserved": "flera uppströmsservrar <0>för specifika domäner</0>;",
|
||||
"example_upstream_comment": "en kommentar.",
|
||||
"upstream_parallel": "Använd parallella förfrågningar för att snabba upp dessa genom att fråga alla uppströmsservrar samtidigt.",
|
||||
"parallel_requests": "Parallella förfrågningar",
|
||||
"load_balancing": "Lastbalansering",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Blockerad skadekod/phishing",
|
||||
"stats_adult": "Blockerade vuxensajter",
|
||||
"stats_query_domain": "Mest eftersökta domäner",
|
||||
"for_last_24_hours": "under de senaste 24 timmarna",
|
||||
"for_last_hours": "för den senaste {{count}} timme",
|
||||
"for_last_hours_plural": "för de senaste {{count}} timmar",
|
||||
"for_last_days": "för den senaste {{count}} dagen",
|
||||
"for_last_days_plural": "för de senaste {{count}} dagarna",
|
||||
"stats_disabled": "Statistiken har inaktiverats. Du kan aktivera det från <0>inställningssidan</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Inga uppströmsdata hittades",
|
||||
"number_of_dns_query_days": "Antalet DNS-förfrågningar som utfördes under senaste {{count}} dagen",
|
||||
"number_of_dns_query_days_plural": "Ett antal DNS förfrågningar utfördes under de senaste {{count}} dagarna",
|
||||
"number_of_dns_query_24_hours": "Antalet DNS-förfrågningar som utfördes under de senaste 24 timmarna",
|
||||
"number_of_dns_query_hours": "Ett antal DNS förfrågningar utfördes för den senaste {{count}} timme",
|
||||
"number_of_dns_query_hours_plural": "Ett antal DNS förfrågningar utfördes för den senaste {{count}} timmar",
|
||||
"number_of_dns_query_blocked_24_hours": "Antalet DNS-förfrågningar som blockerades av annonsfilter och värdens blockeringsklistor",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Antalet DNS-förfrågningar som blockerades av AdGuards modul för surfsäkerhet",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Antalet vuxensajter som blockerats",
|
||||
"enforced_save_search": "Aktivering av Säker surf",
|
||||
"number_of_dns_query_to_safe_search": "Antalet DNS-förfrågningar mot sökmotorer där Säker surf tvingats",
|
||||
"average_processing_time": "Genomsnittlig processtid",
|
||||
"processing_time": "Bearbetningstid",
|
||||
"average_upstream_response_time": "Genomsnittlig svarstid uppströmsserver",
|
||||
"response_time": "Svarstid",
|
||||
"average_processing_time_hint": "Genomsnittlig processtid i millisekunder för DNS-förfrågning",
|
||||
"block_domain_use_filters_and_hosts": "Blockera domäner med filter- och värdfiler",
|
||||
"filters_block_toggle_hint": "Du kan ställa in egna blockerings regler i <a>Filterinställningar</a>.",
|
||||
@@ -306,6 +310,7 @@
|
||||
"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_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",
|
||||
"blocking_mode_default": "Standard: Svara med noll IP-adress (0.0.0.0 för A; :: för AAAA) när det blockeras av regel i Adblock-stil; svara med IP-adressen som anges i regeln när den blockeras av regel i /etc/hosts-stil",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "İstemci ayarları",
|
||||
"example_upstream_reserved": "<0>belirli alan adları</0> için bir üst sunucusu;",
|
||||
"example_multiple_upstreams_reserved": "<0>belirli alanlar için</0> birden fazla üst kaynaklar;",
|
||||
"example_upstream_comment": "bir yorum.",
|
||||
"upstream_parallel": "Tüm üst sunucuları eş zamanlı sorgulayarak çözümlemeyi hızlandırmak için paralel sorgular kullanın.",
|
||||
"parallel_requests": "Paralel istekler",
|
||||
@@ -97,7 +98,7 @@
|
||||
"filters": "Filtreler",
|
||||
"filter": "Filtre",
|
||||
"query_log": "Sorgu Günlüğü",
|
||||
"compact": "Yoğun",
|
||||
"compact": "Sık",
|
||||
"nothing_found": "Hiçbir şey bulunamadı",
|
||||
"faq": "SSS",
|
||||
"version": "Sürüm",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Engellenen kötü amaçlı yazılım ve kimlik avı",
|
||||
"stats_adult": "Engellenen yetişkin içerikli siteler",
|
||||
"stats_query_domain": "Başlıca sorgulanan alan adları",
|
||||
"for_last_24_hours": "son 24 saat içindekiler",
|
||||
"for_last_hours": "son {{count}} saat için",
|
||||
"for_last_hours_plural": "son {{count}} saat için",
|
||||
"for_last_days": "son {{count}} gün boyunca",
|
||||
"for_last_days_plural": "son {{count}} gün boyunca",
|
||||
"stats_disabled": "İstatistikler devre dışı bırakıldı. Bunu, <0>ayarlar sayfasından</0> etkinleştirebilirsiniz.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Üst kaynak verisi bulunamadı",
|
||||
"number_of_dns_query_days": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı",
|
||||
"number_of_dns_query_days_plural": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı",
|
||||
"number_of_dns_query_24_hours": "Son 24 saat içinde işlenen DNS sorgularının sayısı",
|
||||
"number_of_dns_query_hours": "Son {{count}} saat için işlenen DNS sorgularının sayısı",
|
||||
"number_of_dns_query_hours_plural": "Son {{count}} saatiçin işlenen DNS sorgularının sayısı",
|
||||
"number_of_dns_query_blocked_24_hours": "Reklam engelleme filtreleri ve hosts engel listeleri tarafından engellenen DNS isteklerinin sayısı",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "AdGuard gezinti koruması modülü tarafından engellenen DNS isteklerinin sayısı",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Engellenen yetişkin içerikli sitelerin sayısı",
|
||||
"enforced_save_search": "Uygulanan güvenli arama",
|
||||
"number_of_dns_query_to_safe_search": "Güvenli Aramanın uygulandığı arama motorlarına gönderilen DNS isteklerinin sayısı",
|
||||
"average_processing_time": "Ortalama işlem süresi",
|
||||
"processing_time": "İşlem süresi",
|
||||
"average_upstream_response_time": "Ortalama üst kaynak yanıt süresi",
|
||||
"response_time": "Yanıt süresi",
|
||||
"average_processing_time_hint": "Bir DNS isteğinin milisaniye cinsinden ortalama işlem süresi",
|
||||
"block_domain_use_filters_and_hosts": "Filtre ve hosts dosyalarını kullanarak alan adlarını engelle",
|
||||
"filters_block_toggle_hint": "<a>Filtreler</a> ayarlarında engelleme kuralları oluşturabilirsiniz.",
|
||||
@@ -178,7 +182,7 @@
|
||||
"enabled_save_search_toast": "Güvenli Arama etkinleştirildi",
|
||||
"updated_save_search_toast": "Güvenli Arama ayarları güncellendi",
|
||||
"enabled_table_header": "Etkin",
|
||||
"name_table_header": "Ad",
|
||||
"name_table_header": "Adı",
|
||||
"list_url_table_header": "Liste URL'si",
|
||||
"rules_count_table_header": "Kural sayısı",
|
||||
"last_time_updated_table_header": "Son güncelleme zamanı",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "EDNS için özel IP kullan",
|
||||
"edns_use_custom_ip_desc": "EDNS için özel IP kullanımına izin ver",
|
||||
"rate_limit_desc": "İstemci başına izin verilen saniyedeki istek sayısı. 0 olarak ayarlamak, sınır olmadığı anlamına gelir.",
|
||||
"rate_limit_subnet_len_ipv4": "IPv4 adresleri için alt ağ önek uzunluğu",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Hız sınırlaması için kullanılan IPv4 adreslerinin alt ağ önek uzunluğu. Varsayılan 24'tür",
|
||||
"rate_limit_subnet_len_ipv4_error": "IPv4 alt ağ önek uzunluğu 0 ile 32 arasında olmalıdır",
|
||||
"rate_limit_subnet_len_ipv6": "IPv6 adresleri için alt ağ önek uzunluğu",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Hız sınırlaması için kullanılan IPv6 adreslerinin alt ağ önek uzunluğu. Varsayılan 56'tür",
|
||||
"rate_limit_subnet_len_ipv6_error": "IPv6 alt ağ önek uzunluğu 0 ile 128 arasında olmalıdır",
|
||||
"form_enter_rate_limit_subnet_len": "Hız sınırlaması için alt ağ önek uzunluğunu girin",
|
||||
"rate_limit_whitelist": "Hız sınırlama izin listesi",
|
||||
"rate_limit_whitelist_desc": "Hız sınırlamasından hariç tutulan IP adresleri",
|
||||
"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 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",
|
||||
@@ -433,7 +447,7 @@
|
||||
"settings_global": "Genel",
|
||||
"settings_custom": "Özel",
|
||||
"table_client": "İstemci",
|
||||
"table_name": "Ad",
|
||||
"table_name": "AdAdı",
|
||||
"save_btn": "Kaydet",
|
||||
"client_add": "İstemci Ekle",
|
||||
"client_new": "Yeni İstemci",
|
||||
@@ -447,7 +461,7 @@
|
||||
"form_enter_id": "Tanımlayıcı girin",
|
||||
"form_add_id": "Tanımlayıcı ekle",
|
||||
"form_client_name": "İstemci ismi girin",
|
||||
"name": "Ad",
|
||||
"name": "Adı",
|
||||
"client_global_settings": "Genel ayarları kullan",
|
||||
"client_deleted": "\"{{key}}\" istemcisi başarıyla silindi",
|
||||
"client_added": "\"{{key}}\" istemcisi başarıyla eklendi",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Налаштування клієнта",
|
||||
"example_upstream_reserved": "DNS-сервер <0>для певних доменів</0>;",
|
||||
"example_multiple_upstreams_reserved": "кілька DNS-серверів <0>для конкретних доменів</0>;",
|
||||
"example_upstream_comment": "коментар.",
|
||||
"upstream_parallel": "Використовувати паралельні запити, щоб пришвидшити вирішення одночасною чергою всіх оригінальних серверів.",
|
||||
"parallel_requests": "Паралельні запити",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Заблоковано зловмисних/шахрайських програм",
|
||||
"stats_adult": "Заблоковано вебсайтів для дорослих",
|
||||
"stats_query_domain": "Найчастіші запити доменів",
|
||||
"for_last_24_hours": "за останні 24 години",
|
||||
"for_last_hours": "за останню {{count}} годину",
|
||||
"for_last_hours_plural": "за останні {{count}} годин",
|
||||
"for_last_days": "за останній {{count}} день",
|
||||
"for_last_days_plural": "за останні {{count}} днів",
|
||||
"stats_disabled": "Статистику вимкнено. Ви можете увімкнути її на <0>сторінці налаштувань</0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Немає даних про upstream-сервери",
|
||||
"number_of_dns_query_days": "Кількість DNS-запитів, оброблених за останні {{count}} дні",
|
||||
"number_of_dns_query_days_plural": "Кількість DNS-запитів, оброблених за останні {{count}} днів",
|
||||
"number_of_dns_query_24_hours": "Кількість DNS-запитів, оброблених за останні 24 години",
|
||||
"number_of_dns_query_hours": "Кількість DNS-запитів, оброблених за останню {{count}} годину",
|
||||
"number_of_dns_query_hours_plural": "Кількість DNS-запитів, оброблених за останні {{count}} годин",
|
||||
"number_of_dns_query_blocked_24_hours": "Кількість DNS-запитів, заблокованих фільтрами і списками блокування hosts",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Кількість DNS-запитів, заблокованих модулем «Безпека перегляду» AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Кількість заблокованих вебсайтів для дорослих",
|
||||
"enforced_save_search": "Примусовий безпечний пошук",
|
||||
"number_of_dns_query_to_safe_search": "Кількість DNS-запитів до пошукових систем, для яких примусово застосований безпечний пошук",
|
||||
"average_processing_time": "Середній час обробки",
|
||||
"processing_time": "Час обробки",
|
||||
"average_upstream_response_time": "Середній час відгуку upstream-сервера",
|
||||
"response_time": "Час відгуку",
|
||||
"average_processing_time_hint": "Середній час обробки DNS запиту в мілісекундах",
|
||||
"block_domain_use_filters_and_hosts": "Блокування доменів за допомогою фільтрів та hosts-файлів",
|
||||
"filters_block_toggle_hint": "Ви можете налаштувати правила блокування в розділі <a>Фільтри</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Використання користувацької IP-адреси для EDNS",
|
||||
"edns_use_custom_ip_desc": "Дозволити використовувати користувацьку IP-адресу для EDNS",
|
||||
"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-адреса, яку потрібно видати для заблокованого АААА запиту",
|
||||
"blocking_mode_default": "Усталено: відповідь із нульовою IP-адресою (0.0.0.0 для A; :: для AAAA), якщо заблоковано правилом у Adblock-стилі; відповідь зазначеною у правилі IP-адресою, якщо заблокувано правилом у hosts-стилі",
|
||||
@@ -681,7 +695,7 @@
|
||||
"disable_notify_for_minutes_plural": "Вимкнення захисту на {{count}} хвилин",
|
||||
"disable_notify_for_hours": "Вимкнення захисту на {{count}} годину",
|
||||
"disable_notify_for_hours_plural": "Вимкнення захисту на {{count}} годин",
|
||||
"disable_notify_until_tomorrow": "Відключення захисту до завтра",
|
||||
"disable_notify_until_tomorrow": "Вимкнути захист до завтра",
|
||||
"enable_protection_timer": "Захист буде ввімкнено о {{time}}",
|
||||
"custom_retention_input": "Введіть час в годинах",
|
||||
"custom_rotation_input": "Введіть час в годинах",
|
||||
@@ -699,7 +713,7 @@
|
||||
"schedule_current_timezone": "Поточний часовий пояс: {{value}}",
|
||||
"schedule_time_all_day": "Увесь день",
|
||||
"schedule_modal_description": "Цей розклад замінить усі наявні розклади на той самий день тижня. Кожен день тижня може мати тільки один період бездіяльності.",
|
||||
"schedule_modal_time_off": "Блокування сервісів відключена:",
|
||||
"schedule_modal_time_off": "Вимкнення блокування сервісів:",
|
||||
"schedule_new": "Новий розклад",
|
||||
"schedule_edit": "Редагувати розклад",
|
||||
"schedule_save": "Зберегти розклад",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "Cài đặt thiết bị",
|
||||
"example_upstream_reserved": "ngược dòng <0>cho các miền cụ thể</0>;",
|
||||
"example_multiple_upstreams_reserved": "nhiều máy chủ thượng nguồn <0>cho các miền cụ thể</0>;",
|
||||
"example_upstream_comment": "một lời bình luận.",
|
||||
"upstream_parallel": "Sử dụng truy vấn song song để tăng tốc độ giải quyết bằng cách truy vấn đồng thời tất cả các máy chủ ngược tuyến",
|
||||
"parallel_requests": "Yêu cầu song song",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "Mã độc/lừa đảo đã chặn",
|
||||
"stats_adult": "Website người lớn đã chặn",
|
||||
"stats_query_domain": "Tên miền truy vấn nhiều",
|
||||
"for_last_24_hours": "trong 24 giờ qua",
|
||||
"for_last_hours": "trong {{count}} giờ qua",
|
||||
"for_last_hours_plural": "trong {{count}} giờ qua",
|
||||
"for_last_days": "trong {{count}} ngày qua",
|
||||
"for_last_days_plural": "trong {{count}} ngày qua",
|
||||
"stats_disabled": "Số liệu thống kê đã bị vô hiệu hóa. Bạn có thể bật nó từ <0> trang cài đặt </0>.",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "Không tìm thấy dữ liệu máy chủ ngược dòng",
|
||||
"number_of_dns_query_days": "Một số truy vấn DNS được xử lý trong {{count}} ngày qua",
|
||||
"number_of_dns_query_days_plural": "Một số truy vấn DNS được xử lý trong {{count}} ngày qua",
|
||||
"number_of_dns_query_24_hours": "Số yêu cầu DNS đã xử lý trong 24 giờ qua",
|
||||
"number_of_dns_query_hours": "Một số truy vấn DNS được xử lý trong {{count}} giờ qua",
|
||||
"number_of_dns_query_hours_plural": "Một số truy vấn DNS được xử lý trong {{count}} giờ qua",
|
||||
"number_of_dns_query_blocked_24_hours": "Số yêu cầu DNS bị chặn bởi bộ lọc quảng cáo và danh sách chặn host",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "Số yêu cầu DNS bị chặn bởi chế độ bảo vệ duyệt web AdGuard",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "Số trang web người lớn đã chặn",
|
||||
"enforced_save_search": "Bắt buộc tìm kiếm an toàn",
|
||||
"number_of_dns_query_to_safe_search": "Số yêu cầu DNS tới công cụ tìm kiếm đã chuyển thành tìm kiếm an toàn",
|
||||
"average_processing_time": "Thời gian xử lý trung bình",
|
||||
"processing_time": "Thời gian xử lý",
|
||||
"average_upstream_response_time": "Thời gian phản hồi trung bình từ máy chủ thượng nguồn",
|
||||
"response_time": "Thời gian đáp ứng",
|
||||
"average_processing_time_hint": "Thời gian trung bình cho một yêu cầu DNS tính bằng mili giây",
|
||||
"block_domain_use_filters_and_hosts": "Chặn tên miền sử dụng các bộ lọc và file hosts",
|
||||
"filters_block_toggle_hint": "Bạn có thể thiết lập quy tắc chặn tại cài đặt <a>Bộ lọc</a>.",
|
||||
@@ -306,6 +310,16 @@
|
||||
"edns_use_custom_ip": "Sử dụng địa chỉ IP tùy chỉnh cho EDNS",
|
||||
"edns_use_custom_ip_desc": "Cho phép sử dụng địa chỉ IP tùy chỉnh cho EDNS",
|
||||
"rate_limit_desc": "Số lượng yêu cầu mỗi giây mà một khách hàng được phép thực hiện (0: không giới hạn)",
|
||||
"rate_limit_subnet_len_ipv4": "Độ dài tiền tố mạng con cho địa chỉ IPv4",
|
||||
"rate_limit_subnet_len_ipv4_desc": "Độ dài tiền tố mạng con cho các địa chỉ IPv4 được sử dụng để giới hạn tốc độ. Mặc định là 24",
|
||||
"rate_limit_subnet_len_ipv4_error": "Độ dài tiền tố mạng con IPv4 phải nằm trong khoảng từ 0 đến 32",
|
||||
"rate_limit_subnet_len_ipv6": "Độ dài tiền tố mạng con cho địa chỉ IPv6",
|
||||
"rate_limit_subnet_len_ipv6_desc": "Độ dài tiền tố mạng con cho các địa chỉ IPv6 được sử dụng để giới hạn tốc độ. Mặc định là 56",
|
||||
"rate_limit_subnet_len_ipv6_error": "Độ dài tiền tố mạng con IPv6 phải nằm trong khoảng từ 0 đến 128",
|
||||
"form_enter_rate_limit_subnet_len": "Nhập độ dài tiền tố mạng con để giới hạn tốc độ",
|
||||
"rate_limit_whitelist": "Danh sách cho phép giới hạn tỷ lệ",
|
||||
"rate_limit_whitelist_desc": "Địa chỉ IP bị loại trừ khỏi giới hạn tốc độ",
|
||||
"rate_limit_whitelist_placeholder": "Nhập một địa chỉ IP trên mỗi dòng",
|
||||
"blocking_ipv4_desc": "Địa chỉ IP được trả lại cho một yêu cầu A bị chặn",
|
||||
"blocking_ipv6_desc": "Địa chỉ IP được trả lại cho một yêu cầu AAA bị chặn",
|
||||
"blocking_mode_default": "Mặc định: Trả lời với NXDOMAIN khi bị chặn bởi quy tắc kiểu Adblock; phản hồi với địa chỉ IP được chỉ định trong quy tắc khi bị chặn bởi quy tắc / etc / hosts-style",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "客户端设置",
|
||||
"example_upstream_reserved": "指定为<0>特定域名</0>的上游服务器;",
|
||||
"example_multiple_upstreams_reserved": "<0>特定域名</0>的多个上游服务器;",
|
||||
"example_upstream_comment": "注释。",
|
||||
"upstream_parallel": "使用并行请求以同时查询所有上游服务器来加快解析速度。",
|
||||
"parallel_requests": "并行请求",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "被拦截的恶意/钓鱼网站",
|
||||
"stats_adult": "被拦截的成人网站",
|
||||
"stats_query_domain": "请求域名排行",
|
||||
"for_last_24_hours": "在过去 24 小时",
|
||||
"for_last_hours": "最近 {{count}} 小时",
|
||||
"for_last_hours_plural": "最近 {{count}} 小时",
|
||||
"for_last_days": "最近 {{count}} 天",
|
||||
"for_last_days_plural": "最近 {{count}} 天",
|
||||
"stats_disabled": "已禁用统计数据。您可以从<0>设置页面</0>打开它。",
|
||||
@@ -134,14 +136,16 @@
|
||||
"no_upstreams_data_found": "未找到上游服务器数据",
|
||||
"number_of_dns_query_days": "过去 {{count}} 天内处理的 DNS 查询总数",
|
||||
"number_of_dns_query_days_plural": "在过去的 {{count}} 天内处理了多少个 DNS 查询",
|
||||
"number_of_dns_query_24_hours": "过去 24 小时内处理的 DNS 请求总数",
|
||||
"number_of_dns_query_hours": "最近 {{count}} 小时内处理的 DNS 查询次数",
|
||||
"number_of_dns_query_hours_plural": "最近 {{count}} 小时内处理的 DNS 查询次数",
|
||||
"number_of_dns_query_blocked_24_hours": "被广告过滤器和 Hosts 黑名单阻止的 DNS 请求总数",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "被 AdGuard 安全浏览模块阻止的 DNS 请求总数",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "被阻止的成人网站总数",
|
||||
"enforced_save_search": "强制安全搜索",
|
||||
"number_of_dns_query_to_safe_search": "启用强制安全搜索后对搜索引擎的 DNS 请求总数",
|
||||
"average_processing_time": "平均处理时间",
|
||||
"processing_time": "处理时间",
|
||||
"average_upstream_response_time": "上游服务器的平均响应时间",
|
||||
"response_time": "响应时间",
|
||||
"average_processing_time_hint": "处理 DNS 请求的平均时间(毫秒)",
|
||||
"block_domain_use_filters_and_hosts": "使用过滤器和 Hosts 文件以拦截指定域名",
|
||||
"filters_block_toggle_hint": "你可以在 <a>过滤器</a> 设置中添加过滤规则。",
|
||||
@@ -306,6 +310,16 @@
|
||||
"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 地址",
|
||||
"blocking_mode_default": "默认:被 Adblock 规则拦截时反应为零 IP 地址(A记录:0.0.0.0;AAAA记录:::);被 /etc/hosts 规则拦截时反应为规则中指定 IP 地址",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"client_settings": "用戶端設定",
|
||||
"example_upstream_reserved": "<0>供特定的網域</0>之上游;",
|
||||
"example_multiple_upstreams_reserved": "<0>特定網域</0>的多個上游伺服器;",
|
||||
"example_upstream_comment": "註解。",
|
||||
"upstream_parallel": "透過同時地查詢所有上游的伺服器,使用並行的查詢以加速解析。",
|
||||
"parallel_requests": "並行的請求",
|
||||
@@ -8,9 +9,9 @@
|
||||
"load_balancing_desc": "每次查詢一個上游伺服器。AdGuard Home 使用它的加權隨機的演算法來選擇伺服器,以便最快的伺服器被更常使用。",
|
||||
"bootstrap_dns": "自我啟動(Bootstrap)DNS 伺服器",
|
||||
"bootstrap_dns_desc": "DNS 伺服器的 IP 位址,用於解析您指定為上游伺服器的 DoH/DoT 解析器的 IP 位址。不允許註釋。",
|
||||
"fallback_dns_title": "備援 DNS 伺服器",
|
||||
"fallback_dns_desc": "當上游 DNS 伺服器未回應時使用的備援 DNS 伺服器清單。語法與上面的主要上游欄位相同。",
|
||||
"fallback_dns_placeholder": "每行輸入一個備援 DNS 伺服器",
|
||||
"fallback_dns_title": "應變 DNS 伺服器",
|
||||
"fallback_dns_desc": "當上游 DNS 伺服器未回覆時被使用的應變 DNS 伺服器之清單。此語法與在上面主要上游欄位中的相同。",
|
||||
"fallback_dns_placeholder": "每行輸入一個應變 DNS 伺服器",
|
||||
"local_ptr_title": "私人反向的 DNS 伺服器",
|
||||
"local_ptr_desc": "AdGuard Home 用於區域指標(PTR)查詢之 DNS 伺服器。這些伺服器被用於解析有關在私人 IP 範圍的位址之區域指標查詢,例如,\"192.168.12.34\",使用反向的 DNS。如果未被設定,AdGuard Home 使用您的作業系統之預設 DNS 解析器的位址。",
|
||||
"local_ptr_default_resolver": "預設下,AdGuard Home 使用以下反向的 DNS 解析器:{{ip}}。",
|
||||
@@ -119,7 +120,8 @@
|
||||
"stats_malware_phishing": "已封鎖的惡意軟體/網路釣魚",
|
||||
"stats_adult": "已封鎖的成人網站",
|
||||
"stats_query_domain": "熱門已查詢的網域",
|
||||
"for_last_24_hours": "在最近的 24 小時內",
|
||||
"for_last_hours": "在過去的 {{count}} 小時內",
|
||||
"for_last_hours_plural": "在過去的 {{count}} 小時內",
|
||||
"for_last_days": "在最近的 {{count}} 日內",
|
||||
"for_last_days_plural": "在最近的 {{count}} 日內",
|
||||
"stats_disabled": "該統計資料已被禁用。您可從<0>設定頁面</0>中打開它。",
|
||||
@@ -130,18 +132,20 @@
|
||||
"top_clients": "熱門用戶端",
|
||||
"no_clients_found": "無已發現之用戶端",
|
||||
"general_statistics": "一般的統計資料",
|
||||
"top_upstreams": "經常請求的上游伺服器",
|
||||
"top_upstreams": "熱門上游",
|
||||
"no_upstreams_data_found": "找不到上游伺服器資料",
|
||||
"number_of_dns_query_days": "在最近的 {{count}} 日內已處理的 DNS 查詢之數量",
|
||||
"number_of_dns_query_days_plural": "在最近的 {{count}} 日內已處理的 DNS 查詢之數量",
|
||||
"number_of_dns_query_24_hours": "在最近的 24 小時內已處理的 DNS 查詢之數量",
|
||||
"number_of_dns_query_hours": "過去 {{count}} 小時內處理的 DNS 查詢次數",
|
||||
"number_of_dns_query_hours_plural": "過去 {{count}} 小時內處理的 DNS 查詢次數",
|
||||
"number_of_dns_query_blocked_24_hours": "被廣告封鎖過濾器和主機封鎖清單阻擋的 DNS 請求之數量",
|
||||
"number_of_dns_query_blocked_24_hours_by_sec": "被 AdGuard 瀏覽安全模組封鎖的 DNS 請求之數量",
|
||||
"number_of_dns_query_blocked_24_hours_adult": "已封鎖的成人網站之數量",
|
||||
"enforced_save_search": "已強制執行的安全搜尋",
|
||||
"number_of_dns_query_to_safe_search": "安全搜尋已被強制執行之屬於搜尋引擎的 DNS 請求之數量",
|
||||
"average_processing_time": "平均的處理時間",
|
||||
"processing_time": "處理時間",
|
||||
"average_upstream_response_time": "平均的上游回應時間",
|
||||
"response_time": "回應時間",
|
||||
"average_processing_time_hint": "在處理一項 DNS 請求時以毫秒(ms)計的平均時間",
|
||||
"block_domain_use_filters_and_hosts": "透過過濾器和主機檔案封鎖網域",
|
||||
"filters_block_toggle_hint": "您可在<a>過濾器</a>設定中設置封鎖規則。",
|
||||
@@ -286,7 +290,7 @@
|
||||
"blocking_ipv4": "封鎖 IPv4",
|
||||
"blocking_ipv6": "封鎖 IPv6",
|
||||
"blocked_response_ttl": "已封鎖的回應之存活時間(TTL)",
|
||||
"blocked_response_ttl_desc": "指定客戶端應將過濾後的回應存入快取的秒數",
|
||||
"blocked_response_ttl_desc": "對用戶端應快取受過濾的回應,指定多少秒數",
|
||||
"form_enter_blocked_response_ttl": "請輸入已封鎖回應的存活時間(秒)",
|
||||
"dnscrypt": "DNSCrypt",
|
||||
"dns_over_https": "DNS-over-HTTPS",
|
||||
@@ -306,6 +310,16 @@
|
||||
"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 位址",
|
||||
"blocking_mode_default": "預設:當被 AdBlock 樣式的規則封鎖時,以零值 IP 位址(0.0.0.0 供 A;:: 供 AAAA)回覆;當被 /etc/hosts 樣式的規則封鎖時,以在該規則中之已明確指定的 IP 位址回覆",
|
||||
|
||||
@@ -62,6 +62,10 @@ export const setDnsConfig = (config) => async (dispatch) => {
|
||||
data.upstream_dns = splitByNewLine(config.upstream_dns);
|
||||
hasDnsSettings = true;
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(data, 'ratelimit_whitelist')) {
|
||||
data.ratelimit_whitelist = splitByNewLine(config.ratelimit_whitelist);
|
||||
hasDnsSettings = true;
|
||||
}
|
||||
|
||||
await apiClient.setDnsConfig(data);
|
||||
|
||||
|
||||
@@ -338,6 +338,40 @@ export const getDnsStatus = () => async (dispatch) => {
|
||||
}
|
||||
};
|
||||
|
||||
export const timerStatusRequest = createAction('TIMER_STATUS_REQUEST');
|
||||
export const timerStatusFailure = createAction('TIMER_STATUS_FAILURE');
|
||||
export const timerStatusSuccess = createAction('TIMER_STATUS_SUCCESS');
|
||||
|
||||
export const getTimerStatus = () => async (dispatch) => {
|
||||
dispatch(timerStatusRequest());
|
||||
|
||||
const handleRequestError = () => {
|
||||
dispatch(addErrorToast({ error: 'dns_status_error' }));
|
||||
dispatch(dnsStatusFailure());
|
||||
window.location.reload(true);
|
||||
};
|
||||
|
||||
const handleRequestSuccess = (response) => {
|
||||
const dnsStatus = response.data;
|
||||
if (dnsStatus.protection_disabled_duration === 0) {
|
||||
dnsStatus.protection_disabled_duration = null;
|
||||
}
|
||||
const { running } = dnsStatus;
|
||||
const runningStatus = dnsStatus && running;
|
||||
if (runningStatus === true) {
|
||||
dispatch(timerStatusSuccess(dnsStatus));
|
||||
} else {
|
||||
dispatch(setDnsRunningStatus(running));
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
checkStatus(handleRequestSuccess, handleRequestError);
|
||||
} catch (error) {
|
||||
handleRequestError();
|
||||
}
|
||||
};
|
||||
|
||||
export const testUpstreamRequest = createAction('TEST_UPSTREAM_REQUEST');
|
||||
export const testUpstreamFailure = createAction('TEST_UPSTREAM_FAILURE');
|
||||
export const testUpstreamSuccess = createAction('TEST_UPSTREAM_SUCCESS');
|
||||
|
||||
@@ -118,6 +118,11 @@ body {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-body--filters {
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.modal-body__item:not(:first-child) {
|
||||
padding-top: 1.5rem;
|
||||
}
|
||||
@@ -134,15 +139,6 @@ body {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.button-action {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.logs__row:hover .button-action,
|
||||
.button-action--active {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.ReactModal__Body--open {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import {
|
||||
} from '../../helpers/constants';
|
||||
import { getLogsUrlParams, setHtmlLangAttr, setUITheme } from '../../helpers/helpers';
|
||||
import Header from '../Header';
|
||||
import { changeLanguage, getDnsStatus } from '../../actions';
|
||||
import { changeLanguage, getDnsStatus, getTimerStatus } from '../../actions';
|
||||
|
||||
import Dashboard from '../../containers/Dashboard';
|
||||
import SetupGuide from '../../containers/SetupGuide';
|
||||
@@ -126,6 +126,18 @@ const App = () => {
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(getDnsStatus());
|
||||
|
||||
const handleVisibilityChange = () => {
|
||||
if (document.visibilityState === 'visible') {
|
||||
dispatch(getTimerStatus());
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener('visibilitychange', handleVisibilityChange);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
||||
};
|
||||
}, []);
|
||||
|
||||
const setLanguage = () => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import Cell from '../ui/Cell';
|
||||
import DomainCell from './DomainCell';
|
||||
|
||||
import { getPercent } from '../../helpers/helpers';
|
||||
import { STATUS_COLORS } from '../../helpers/constants';
|
||||
import { DASHBOARD_TABLES_DEFAULT_PAGE_SIZE, STATUS_COLORS, TABLES_MIN_ROWS } from '../../helpers/constants';
|
||||
|
||||
const CountCell = (totalBlocked) => function cell(row) {
|
||||
const { value } = row;
|
||||
@@ -62,8 +62,8 @@ const BlockedDomains = ({
|
||||
]}
|
||||
showPagination={false}
|
||||
noDataText={t('no_domains_found')}
|
||||
minRows={6}
|
||||
defaultPageSize={100}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
defaultPageSize={DASHBOARD_TABLES_DEFAULT_PAGE_SIZE}
|
||||
className="-highlight card-table-overflow--limited stats__table"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import ReactTable from 'react-table';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
@@ -9,10 +9,16 @@ import Card from '../ui/Card';
|
||||
import Cell from '../ui/Cell';
|
||||
|
||||
import { getPercent, sortIp } from '../../helpers/helpers';
|
||||
import { BLOCK_ACTIONS, STATUS_COLORS } from '../../helpers/constants';
|
||||
import {
|
||||
BLOCK_ACTIONS,
|
||||
DASHBOARD_TABLES_DEFAULT_PAGE_SIZE,
|
||||
STATUS_COLORS,
|
||||
TABLES_MIN_ROWS,
|
||||
} from '../../helpers/constants';
|
||||
import { toggleClientBlock } from '../../actions/access';
|
||||
import { renderFormattedClientCell } from '../../helpers/renderFormattedClientCell';
|
||||
import { getStats } from '../../actions/stats';
|
||||
import IconTooltip from '../Logs/Cells/IconTooltip';
|
||||
|
||||
const getClientsPercentColor = (percent) => {
|
||||
if (percent > 50) {
|
||||
@@ -40,9 +46,7 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => {
|
||||
const processingSet = useSelector((state) => state.access.processingSet);
|
||||
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||
|
||||
const buttonClass = classNames('button-action button-action--main', {
|
||||
'button-action--unblock': disallowed,
|
||||
});
|
||||
const [isOptionsOpened, setOptionsOpened] = useState(false);
|
||||
|
||||
const toggleClientStatus = async (ip, disallowed, disallowed_rule) => {
|
||||
let confirmMessage;
|
||||
@@ -62,23 +66,49 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => {
|
||||
}
|
||||
};
|
||||
|
||||
const onClick = () => toggleClientStatus(ip, disallowed, disallowed_rule);
|
||||
const onClick = () => {
|
||||
toggleClientStatus(ip, disallowed, disallowed_rule);
|
||||
setOptionsOpened(false);
|
||||
};
|
||||
|
||||
const text = disallowed ? BLOCK_ACTIONS.UNBLOCK : BLOCK_ACTIONS.BLOCK;
|
||||
|
||||
const lastRuleInAllowlist = !disallowed && allowedСlients === disallowed_rule;
|
||||
const disabled = processingSet || lastRuleInAllowlist;
|
||||
return (
|
||||
<div className="table__action pl-4">
|
||||
<div className="table__action">
|
||||
<button
|
||||
type="button"
|
||||
className={buttonClass}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
title={lastRuleInAllowlist ? t('last_rule_in_allowlist', { disallowed_rule }) : ''}
|
||||
className="btn btn-icon btn-sm px-0"
|
||||
onClick={() => setOptionsOpened(true)}
|
||||
>
|
||||
<Trans>{text}</Trans>
|
||||
<svg className="icon24 icon--lightgray button-action__icon">
|
||||
<use xlinkHref="#bullets" />
|
||||
</svg>
|
||||
</button>
|
||||
{isOptionsOpened && (
|
||||
<IconTooltip
|
||||
className="icon24"
|
||||
tooltipClass="button-action--arrow-option-container"
|
||||
xlinkHref="bullets"
|
||||
triggerClass="btn btn-icon btn-sm px-0 button-action__hidden-trigger"
|
||||
content={(
|
||||
<button
|
||||
className={classNames('button-action--arrow-option px-4 py-1', disallowed ? 'bg--green' : 'bg--danger')}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
title={lastRuleInAllowlist ? t('last_rule_in_allowlist', { disallowed_rule }) : ''}
|
||||
>
|
||||
<Trans>{text}</Trans>
|
||||
</button>
|
||||
)}
|
||||
placement="bottom-end"
|
||||
trigger="click"
|
||||
onVisibilityChange={setOptionsOpened}
|
||||
defaultTooltipShown={true}
|
||||
delayHide={0}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -134,8 +164,8 @@ const Clients = ({
|
||||
]}
|
||||
showPagination={false}
|
||||
noDataText={t('no_clients_found')}
|
||||
minRows={6}
|
||||
defaultPageSize={100}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
defaultPageSize={DASHBOARD_TABLES_DEFAULT_PAGE_SIZE}
|
||||
className="-highlight card-table-overflow--limited clients__table"
|
||||
getTrProps={(_state, rowInfo) => {
|
||||
if (!rowInfo) {
|
||||
|
||||
@@ -4,9 +4,9 @@ import { Trans, useTranslation } from 'react-i18next';
|
||||
import round from 'lodash/round';
|
||||
import { shallowEqual, useSelector } from 'react-redux';
|
||||
import Card from '../ui/Card';
|
||||
import { formatNumber } from '../../helpers/helpers';
|
||||
import { formatNumber, msToDays, msToHours } from '../../helpers/helpers';
|
||||
import LogsSearchLink from '../ui/LogsSearchLink';
|
||||
import { RESPONSE_FILTER, DAY } from '../../helpers/constants';
|
||||
import { RESPONSE_FILTER, TIME_UNITS } from '../../helpers/constants';
|
||||
import Tooltip from '../ui/Tooltip';
|
||||
|
||||
const Row = ({
|
||||
@@ -52,14 +52,19 @@ const Counters = ({ refreshButton, subtitle }) => {
|
||||
numReplacedParental,
|
||||
numReplacedSafesearch,
|
||||
avgProcessingTime,
|
||||
timeUnits,
|
||||
} = useSelector((state) => state.stats, shallowEqual);
|
||||
const { t } = useTranslation();
|
||||
const days = interval / DAY;
|
||||
|
||||
const dnsQueryTooltip = timeUnits === TIME_UNITS.HOURS
|
||||
? t('number_of_dns_query_hours', { count: msToHours(interval) })
|
||||
: t('number_of_dns_query_days', { count: msToDays(interval) });
|
||||
|
||||
const rows = [
|
||||
{
|
||||
label: 'dns_query',
|
||||
count: numDnsQueries,
|
||||
tooltipTitle: days === 1 ? 'number_of_dns_query_24_hours' : t('number_of_dns_query_days', { count: days }),
|
||||
tooltipTitle: dnsQueryTooltip,
|
||||
response_status: RESPONSE_FILTER.ALL.QUERY,
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,11 +28,14 @@
|
||||
border-bottom: 6px solid #585965;
|
||||
}
|
||||
|
||||
@media (max-width: 1279.98px) {
|
||||
.table__action {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
}
|
||||
.table__action {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.table__action .btn-icon {
|
||||
outline: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.page-title--dashboard {
|
||||
|
||||
@@ -7,7 +7,7 @@ import Card from '../ui/Card';
|
||||
import Cell from '../ui/Cell';
|
||||
import DomainCell from './DomainCell';
|
||||
|
||||
import { STATUS_COLORS } from '../../helpers/constants';
|
||||
import { DASHBOARD_TABLES_DEFAULT_PAGE_SIZE, STATUS_COLORS, TABLES_MIN_ROWS } from '../../helpers/constants';
|
||||
import { getPercent } from '../../helpers/helpers';
|
||||
|
||||
const getQueriedPercentColor = (percent) => {
|
||||
@@ -58,8 +58,8 @@ const QueriedDomains = ({
|
||||
]}
|
||||
showPagination={false}
|
||||
noDataText={t('no_domains_found')}
|
||||
minRows={6}
|
||||
defaultPageSize={100}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
defaultPageSize={DASHBOARD_TABLES_DEFAULT_PAGE_SIZE}
|
||||
className="-highlight card-table-overflow--limited stats__table"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -6,6 +6,7 @@ import { withTranslation, Trans } from 'react-i18next';
|
||||
|
||||
import Card from '../ui/Card';
|
||||
import DomainCell from './DomainCell';
|
||||
import { DASHBOARD_TABLES_DEFAULT_PAGE_SIZE, TABLES_MIN_ROWS } from '../../helpers/constants';
|
||||
|
||||
const TimeCell = ({ value }) => {
|
||||
if (!value) {
|
||||
@@ -37,7 +38,7 @@ const UpstreamAvgTime = ({
|
||||
subtitle,
|
||||
}) => (
|
||||
<Card
|
||||
title={t('average_processing_time')}
|
||||
title={t('average_upstream_response_time')}
|
||||
subtitle={subtitle}
|
||||
bodyType="card-table"
|
||||
refresh={refreshButton}
|
||||
@@ -54,7 +55,7 @@ const UpstreamAvgTime = ({
|
||||
Cell: DomainCell,
|
||||
},
|
||||
{
|
||||
Header: <Trans>processing_time</Trans>,
|
||||
Header: <Trans>response_time</Trans>,
|
||||
accessor: 'count',
|
||||
maxWidth: 190,
|
||||
Cell: TimeCell,
|
||||
@@ -62,8 +63,8 @@ const UpstreamAvgTime = ({
|
||||
]}
|
||||
showPagination={false}
|
||||
noDataText={t('no_upstreams_data_found')}
|
||||
minRows={6}
|
||||
defaultPageSize={100}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
defaultPageSize={DASHBOARD_TABLES_DEFAULT_PAGE_SIZE}
|
||||
className="-highlight card-table-overflow--limited stats__table"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -8,7 +8,7 @@ import Cell from '../ui/Cell';
|
||||
import DomainCell from './DomainCell';
|
||||
|
||||
import { getPercent } from '../../helpers/helpers';
|
||||
import { STATUS_COLORS } from '../../helpers/constants';
|
||||
import { DASHBOARD_TABLES_DEFAULT_PAGE_SIZE, STATUS_COLORS, TABLES_MIN_ROWS } from '../../helpers/constants';
|
||||
|
||||
const CountCell = (totalBlocked) => (
|
||||
function cell(row) {
|
||||
@@ -64,8 +64,8 @@ const UpstreamResponses = ({
|
||||
]}
|
||||
showPagination={false}
|
||||
noDataText={t('no_upstreams_data_found')}
|
||||
minRows={6}
|
||||
defaultPageSize={100}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
defaultPageSize={DASHBOARD_TABLES_DEFAULT_PAGE_SIZE}
|
||||
className="-highlight card-table-overflow--limited stats__table"
|
||||
/>
|
||||
</Card>
|
||||
|
||||
@@ -9,7 +9,12 @@ import Counters from './Counters';
|
||||
import Clients from './Clients';
|
||||
import QueriedDomains from './QueriedDomains';
|
||||
import BlockedDomains from './BlockedDomains';
|
||||
import { DISABLE_PROTECTION_TIMINGS, ONE_SECOND_IN_MS, SETTINGS_URLS } from '../../helpers/constants';
|
||||
import {
|
||||
DISABLE_PROTECTION_TIMINGS,
|
||||
ONE_SECOND_IN_MS,
|
||||
SETTINGS_URLS,
|
||||
TIME_UNITS,
|
||||
} from '../../helpers/constants';
|
||||
import {
|
||||
msToSeconds,
|
||||
msToMinutes,
|
||||
@@ -46,15 +51,12 @@ const Dashboard = ({
|
||||
getAllStats();
|
||||
}, []);
|
||||
const getSubtitle = () => {
|
||||
const ONE_DAY = 1;
|
||||
const intervalInDays = msToDays(stats.interval);
|
||||
|
||||
if (intervalInDays < ONE_DAY) {
|
||||
if (!stats.enabled) {
|
||||
return t('stats_disabled_short');
|
||||
}
|
||||
|
||||
return intervalInDays === ONE_DAY
|
||||
? t('for_last_24_hours')
|
||||
return stats.timeUnits === TIME_UNITS.HOURS
|
||||
? t('for_last_hours', { count: msToHours(stats.interval) })
|
||||
: t('for_last_days', { count: msToDays(stats.interval) });
|
||||
};
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ const renderIcons = (iconsData) => iconsData.map(({
|
||||
}) => <a key={iconName} href={href} target="_blank" rel="noopener noreferrer"
|
||||
className={classNames('d-flex align-items-center', className)}
|
||||
>
|
||||
<svg className="nav-icon nav-icon--gray">
|
||||
<svg className="icon icon--15 mr-1 icon--gray">
|
||||
<use xlinkHref={`#${iconName}`} />
|
||||
</svg>
|
||||
</a>);
|
||||
@@ -110,7 +110,7 @@ const Form = (props) => {
|
||||
const openAddFiltersModal = () => openModal(MODAL_TYPE.ADD_FILTERS);
|
||||
|
||||
return <form onSubmit={handleSubmit}>
|
||||
<div className="modal-body modal-body--medium">
|
||||
<div className="modal-body modal-body--filters">
|
||||
{modalType === MODAL_TYPE.SELECT_MODAL_TYPE
|
||||
&& <div className="d-flex justify-content-around">
|
||||
<button onClick={openFilteringListModal}
|
||||
|
||||
@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
||||
import ReactTable from 'react-table';
|
||||
import { withTranslation } from 'react-i18next';
|
||||
import { sortIp } from '../../../helpers/helpers';
|
||||
import { MODAL_TYPE } from '../../../helpers/constants';
|
||||
import { MODAL_TYPE, TABLES_MIN_ROWS } from '../../../helpers/constants';
|
||||
import { LocalStorageHelper, LOCAL_STORAGE_KEYS } from '../../../helpers/localStorageHelper';
|
||||
|
||||
class Table extends Component {
|
||||
@@ -88,7 +88,7 @@ class Table extends Component {
|
||||
showPagination
|
||||
defaultPageSize={LocalStorageHelper.getItem(LOCAL_STORAGE_KEYS.REWRITES_PAGE_SIZE) || 10}
|
||||
onPageSizeChange={(size) => LocalStorageHelper.setItem(LOCAL_STORAGE_KEYS.REWRITES_PAGE_SIZE, size)}
|
||||
minRows={5}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
ofText="/"
|
||||
previousText={t('previous_btn')}
|
||||
nextText={t('next_btn')}
|
||||
|
||||
@@ -81,6 +81,10 @@ export const Modal = ({
|
||||
};
|
||||
});
|
||||
|
||||
if (timezone !== intialTimezone) {
|
||||
newSchedule.time_zone = timezone;
|
||||
}
|
||||
|
||||
onSubmit(newSchedule);
|
||||
};
|
||||
|
||||
|
||||
@@ -26,9 +26,7 @@ const ClientCell = ({
|
||||
const { t } = useTranslation();
|
||||
const dispatch = useDispatch();
|
||||
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
||||
const processingRules = useSelector((state) => state.filtering.processingRules);
|
||||
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
|
||||
const processingSet = useSelector((state) => state.access.processingSet);
|
||||
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||
const [isOptionsOpened, setOptionsOpened] = useState(false);
|
||||
|
||||
@@ -84,11 +82,23 @@ const ClientCell = ({
|
||||
const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only';
|
||||
const clientNameBlockingFor = getBlockingClientName(clients, client);
|
||||
|
||||
const onClick = async () => {
|
||||
await dispatch(toggleBlocking(buttonType, domain));
|
||||
await dispatch(getStats());
|
||||
setOptionsOpened(false);
|
||||
};
|
||||
|
||||
const BUTTON_OPTIONS = [
|
||||
{
|
||||
name: buttonType,
|
||||
onClick,
|
||||
className: isFiltered ? 'bg--green' : 'bg--danger',
|
||||
},
|
||||
{
|
||||
name: blockingForClientKey,
|
||||
onClick: () => {
|
||||
dispatch(toggleBlockingForClient(buttonType, domain, clientNameBlockingFor));
|
||||
setOptionsOpened(false);
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -101,27 +111,25 @@ const ClientCell = ({
|
||||
client_info?.disallowed_rule || '',
|
||||
));
|
||||
await dispatch(updateLogs());
|
||||
setOptionsOpened(false);
|
||||
}
|
||||
},
|
||||
disabled: processingSet || lastRuleInAllowlist,
|
||||
disabled: lastRuleInAllowlist,
|
||||
},
|
||||
];
|
||||
|
||||
const onClick = async () => {
|
||||
await dispatch(toggleBlocking(buttonType, domain));
|
||||
await dispatch(getStats());
|
||||
};
|
||||
|
||||
const getOptions = (options) => {
|
||||
if (options.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
{options.map(({ name, onClick, disabled }) => (
|
||||
{options.map(({
|
||||
name, onClick, disabled, className,
|
||||
}) => (
|
||||
<button
|
||||
key={name}
|
||||
className="button-action--arrow-option px-4 py-1"
|
||||
className={classNames('button-action--arrow-option px-4 py-1', className)}
|
||||
onClick={onClick}
|
||||
disabled={disabled}
|
||||
>
|
||||
@@ -134,17 +142,6 @@ const ClientCell = ({
|
||||
|
||||
const content = getOptions(BUTTON_OPTIONS);
|
||||
|
||||
const buttonClass = classNames('button-action button-action--main', {
|
||||
'button-action--unblock': isFiltered,
|
||||
'button-action--with-options': content,
|
||||
'button-action--active': isOptionsOpened,
|
||||
});
|
||||
|
||||
const buttonArrowClass = classNames('button-action button-action--arrow', {
|
||||
'button-action--unblock': isFiltered,
|
||||
'button-action--active': isOptionsOpened,
|
||||
});
|
||||
|
||||
const containerClass = classNames('button-action__container', {
|
||||
'button-action__container--detailed': isDetailed,
|
||||
});
|
||||
@@ -153,25 +150,26 @@ const ClientCell = ({
|
||||
<div className={containerClass}>
|
||||
<button
|
||||
type="button"
|
||||
className={buttonClass}
|
||||
onClick={onClick}
|
||||
disabled={processingRules}
|
||||
className="btn btn-icon btn-sm px-0"
|
||||
onClick={() => setOptionsOpened(true)}
|
||||
>
|
||||
{t(buttonType)}
|
||||
<svg className="icon24 icon--lightgray button-action__icon">
|
||||
<use xlinkHref="#bullets" />
|
||||
</svg>
|
||||
</button>
|
||||
{content && (
|
||||
<button className={buttonArrowClass} disabled={processingRules}>
|
||||
<IconTooltip
|
||||
className="icon24"
|
||||
tooltipClass="button-action--arrow-option-container"
|
||||
xlinkHref="chevron-down"
|
||||
triggerClass="button-action--icon"
|
||||
content={content}
|
||||
placement="bottom-end"
|
||||
trigger="click"
|
||||
onVisibilityChange={setOptionsOpened}
|
||||
/>
|
||||
</button>
|
||||
{isOptionsOpened && (
|
||||
<IconTooltip
|
||||
className="icon24"
|
||||
tooltipClass="button-action--arrow-option-container"
|
||||
xlinkHref="bullets"
|
||||
triggerClass="btn btn-icon btn-sm px-0 button-action__hidden-trigger"
|
||||
content={content}
|
||||
placement="bottom-end"
|
||||
trigger="click"
|
||||
onVisibilityChange={setOptionsOpened}
|
||||
defaultTooltipShown={true}
|
||||
delayHide={0}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
@@ -198,7 +196,7 @@ const ClientCell = ({
|
||||
</div>
|
||||
{isDetailed && clientName && !whoisAvailable && (
|
||||
<Link
|
||||
className="detailed-info d-none d-sm-block logs__text logs__text--link"
|
||||
className="detailed-info d-none d-sm-block logs__text logs__text--link logs__text--client"
|
||||
to={`logs?search="${encodeURIComponent(clientName)}"`}
|
||||
title={clientName}
|
||||
>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
.tooltip-custom__container {
|
||||
min-width: 150px;
|
||||
padding: 1rem 1.5rem 1.25rem 1.5rem;
|
||||
font-size: 16px !important;
|
||||
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2);
|
||||
|
||||
@@ -21,6 +21,8 @@ const IconTooltip = ({
|
||||
content,
|
||||
trigger,
|
||||
onVisibilityChange,
|
||||
defaultTooltipShown,
|
||||
delayHide,
|
||||
renderContent = content ? React.Children.map(
|
||||
processContent(content),
|
||||
(item, idx) => <div key={idx} className={contentItemClass}>
|
||||
@@ -44,6 +46,8 @@ const IconTooltip = ({
|
||||
trigger={trigger}
|
||||
onVisibilityChange={onVisibilityChange}
|
||||
delayShow={trigger === 'click' ? 0 : SHOW_TOOLTIP_DELAY}
|
||||
delayHide={delayHide}
|
||||
defaultTooltipShown={defaultTooltipShown}
|
||||
>
|
||||
{xlinkHref && <svg className={className}>
|
||||
<use xlinkHref={`#${xlinkHref}`} />
|
||||
@@ -65,6 +69,8 @@ IconTooltip.propTypes = {
|
||||
content: PropTypes.node,
|
||||
renderContent: PropTypes.arrayOf(PropTypes.element),
|
||||
onVisibilityChange: PropTypes.func,
|
||||
defaultTooltipShown: PropTypes.bool,
|
||||
delayHide: PropTypes.number,
|
||||
};
|
||||
|
||||
export default IconTooltip;
|
||||
|
||||
@@ -80,6 +80,10 @@
|
||||
color: var(--gray-f3);
|
||||
}
|
||||
|
||||
.logs__table .logs__text--client {
|
||||
padding-right: 32px;
|
||||
}
|
||||
|
||||
.icon--selected {
|
||||
background-color: var(--gray-f3);
|
||||
border: solid 1px var(--gray-d8);
|
||||
@@ -261,9 +265,8 @@
|
||||
.button-action__container {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
right: 2px;
|
||||
bottom: 0.5rem;
|
||||
height: 1.6rem;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 1024px) {
|
||||
@@ -307,45 +310,10 @@
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
|
||||
.button-action--arrow {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-left: 1px solid var(--white);
|
||||
width: 1.5625rem;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button-action:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.button-action--arrow .button-action--icon {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.button-action:active {
|
||||
background: var(--btn-block-active);
|
||||
}
|
||||
|
||||
.button-action--unblock:active {
|
||||
background: var(--btn-unblock-active);
|
||||
}
|
||||
|
||||
.button-action:disabled {
|
||||
background: var(--btn-block-disabled);
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.button-action--unblock:disabled {
|
||||
background: var(--btn-unblock-disabled);
|
||||
}
|
||||
|
||||
.button-action--arrow-option {
|
||||
background: transparent;
|
||||
border: 0;
|
||||
@@ -551,3 +519,20 @@
|
||||
padding: 1rem 1.5rem;
|
||||
background-color: var(--card-bgcolor);
|
||||
}
|
||||
|
||||
.button-action__hidden-trigger {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 1px;
|
||||
height: 33px;
|
||||
margin: -1px;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .button-action__icon {
|
||||
color: var(--gray-f3);
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import whoisCell from './whoisCell';
|
||||
import LogsSearchLink from '../../ui/LogsSearchLink';
|
||||
import { sortIp } from '../../../helpers/helpers';
|
||||
import { LocalStorageHelper, LOCAL_STORAGE_KEYS } from '../../../helpers/localStorageHelper';
|
||||
import { TABLES_MIN_ROWS } from '../../../helpers/constants';
|
||||
|
||||
const COLUMN_MIN_WIDTH = 200;
|
||||
|
||||
@@ -90,7 +91,7 @@ class AutoClients extends Component {
|
||||
onPageSizeChange={(size) => (
|
||||
LocalStorageHelper.setItem(LOCAL_STORAGE_KEYS.AUTO_CLIENTS_PAGE_SIZE, size)
|
||||
)}
|
||||
minRows={5}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
ofText="/"
|
||||
previousText={t('previous_btn')}
|
||||
nextText={t('next_btn')}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
sortIp,
|
||||
getService,
|
||||
} from '../../../../helpers/helpers';
|
||||
import { MODAL_TYPE, LOCAL_TIMEZONE_VALUE } from '../../../../helpers/constants';
|
||||
import { MODAL_TYPE, LOCAL_TIMEZONE_VALUE, TABLES_MIN_ROWS } from '../../../../helpers/constants';
|
||||
import Card from '../../../ui/Card';
|
||||
import CellWrap from '../../../ui/CellWrap';
|
||||
import LogsSearchLink from '../../../ui/LogsSearchLink';
|
||||
@@ -79,6 +79,10 @@ const ClientsTable = ({
|
||||
} else {
|
||||
config.tags = [];
|
||||
}
|
||||
|
||||
if (typeof values.upstreams_cache_size === 'string') {
|
||||
config.upstreams_cache_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (modalType === MODAL_TYPE.EDIT_FILTERS) {
|
||||
@@ -347,7 +351,7 @@ const ClientsTable = ({
|
||||
onPageSizeChange={(size) => (
|
||||
LocalStorageHelper.setItem(LOCAL_STORAGE_KEYS.CLIENTS_PAGE_SIZE, size)
|
||||
)}
|
||||
minRows={5}
|
||||
minRows={TABLES_MIN_ROWS}
|
||||
ofText="/"
|
||||
previousText={t('previous_btn')}
|
||||
nextText={t('next_btn')}
|
||||
|
||||
@@ -12,8 +12,13 @@ import i18n from '../../../i18n';
|
||||
import Tabs from '../../ui/Tabs';
|
||||
import Examples from '../Dns/Upstream/Examples';
|
||||
import { ScheduleForm } from '../../Filters/Services/ScheduleForm';
|
||||
import { toggleAllServices, trimLinesAndRemoveEmpty, captitalizeWords } from '../../../helpers/helpers';
|
||||
import {
|
||||
toggleAllServices,
|
||||
trimLinesAndRemoveEmpty,
|
||||
captitalizeWords,
|
||||
} from '../../../helpers/helpers';
|
||||
import {
|
||||
toNumber,
|
||||
renderInputField,
|
||||
renderGroupField,
|
||||
CheckboxField,
|
||||
@@ -21,7 +26,7 @@ import {
|
||||
renderTextareaField,
|
||||
} from '../../../helpers/form';
|
||||
import { validateClientId, validateRequiredValue } from '../../../helpers/validators';
|
||||
import { CLIENT_ID_LINK, FORM_NAME } from '../../../helpers/constants';
|
||||
import { CLIENT_ID_LINK, FORM_NAME, UINT32_RANGE } from '../../../helpers/constants';
|
||||
import './Service.css';
|
||||
|
||||
const settingsCheckboxes = [
|
||||
@@ -307,6 +312,35 @@ let Form = (props) => {
|
||||
normalizeOnBlur={trimLinesAndRemoveEmpty}
|
||||
/>
|
||||
<Examples />
|
||||
<div className="form__label--bold mt-5 mb-3">
|
||||
{t('upstream_dns_cache_configuration')}
|
||||
</div>
|
||||
<div className="form__group mb-2">
|
||||
<Field
|
||||
name="upstreams_cache_enabled"
|
||||
type="checkbox"
|
||||
component={CheckboxField}
|
||||
placeholder={t('enable_upstream_dns_cache')}
|
||||
/>
|
||||
</div>
|
||||
<div className="form__group form__group--settings">
|
||||
<label
|
||||
htmlFor="upstreams_cache_size"
|
||||
className="form__label"
|
||||
>
|
||||
{t('dns_cache_size')}
|
||||
</label>
|
||||
<Field
|
||||
name="upstreams_cache_size"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
placeholder={t('enter_cache_size')}
|
||||
className="form-control"
|
||||
normalize={toNumber}
|
||||
min={0}
|
||||
max={UINT32_RANGE.MAX}
|
||||
/>
|
||||
</div>
|
||||
</div>,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@ class Leases extends Component {
|
||||
<div className="logs__row logs__row--center">
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-icon btn-icon--green btn-outline-secondary btn-sm"
|
||||
className="btn btn-icon btn-icon--green btn-outline-success btn-sm"
|
||||
title={t('make_static')}
|
||||
onClick={this.convertToStatic(row)}
|
||||
disabled={disabledLeasesButton}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
||||
import {
|
||||
renderInputField,
|
||||
renderRadioField,
|
||||
renderTextareaField,
|
||||
CheckboxField,
|
||||
toNumber,
|
||||
} from '../../../../helpers/form';
|
||||
@@ -14,7 +15,10 @@ import {
|
||||
validateIpv6,
|
||||
validateRequiredValue,
|
||||
validateIp,
|
||||
validateIPv4Subnet,
|
||||
validateIPv6Subnet,
|
||||
} from '../../../../helpers/validators';
|
||||
import { removeEmptyLines } from '../../../../helpers/helpers';
|
||||
import { BLOCKING_MODES, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants';
|
||||
|
||||
const checkboxes = [
|
||||
@@ -90,6 +94,69 @@ const Form = ({
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-7">
|
||||
<div className="form__group form__group--settings">
|
||||
<label htmlFor="ratelimit_subnet_len_ipv4"
|
||||
className="form__label form__label--with-desc">
|
||||
<Trans>rate_limit_subnet_len_ipv4</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>rate_limit_subnet_len_ipv4_desc</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name="ratelimit_subnet_len_ipv4"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_rate_limit_subnet_len')}
|
||||
normalize={toNumber}
|
||||
validate={[validateRequiredValue, validateIPv4Subnet]}
|
||||
min={0}
|
||||
max={32}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-7">
|
||||
<div className="form__group form__group--settings">
|
||||
<label htmlFor="ratelimit_subnet_len_ipv6"
|
||||
className="form__label form__label--with-desc">
|
||||
<Trans>rate_limit_subnet_len_ipv6</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>rate_limit_subnet_len_ipv6_desc</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name="ratelimit_subnet_len_ipv6"
|
||||
type="number"
|
||||
component={renderInputField}
|
||||
className="form-control"
|
||||
placeholder={t('form_enter_rate_limit_subnet_len')}
|
||||
normalize={toNumber}
|
||||
validate={[validateRequiredValue, validateIPv6Subnet]}
|
||||
min={0}
|
||||
max={128}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12 col-md-7">
|
||||
<div className="form__group form__group--settings">
|
||||
<label htmlFor="ratelimit_whitelist"
|
||||
className="form__label form__label--with-desc">
|
||||
<Trans>rate_limit_whitelist</Trans>
|
||||
</label>
|
||||
<div className="form__desc form__desc--top">
|
||||
<Trans>rate_limit_whitelist_desc</Trans>
|
||||
</div>
|
||||
<Field
|
||||
name="ratelimit_whitelist"
|
||||
component={renderTextareaField}
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder={t('rate_limit_whitelist_placeholder')}
|
||||
normalizeOnBlur={removeEmptyLines}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-12">
|
||||
<div className="form__group form__group--settings">
|
||||
<Field
|
||||
|
||||
@@ -11,6 +11,9 @@ const Config = () => {
|
||||
const {
|
||||
blocking_mode,
|
||||
ratelimit,
|
||||
ratelimit_subnet_len_ipv4,
|
||||
ratelimit_subnet_len_ipv6,
|
||||
ratelimit_whitelist,
|
||||
blocking_ipv4,
|
||||
blocking_ipv6,
|
||||
blocked_response_ttl,
|
||||
@@ -36,6 +39,9 @@ const Config = () => {
|
||||
<Form
|
||||
initialValues={{
|
||||
ratelimit,
|
||||
ratelimit_subnet_len_ipv4,
|
||||
ratelimit_subnet_len_ipv6,
|
||||
ratelimit_whitelist,
|
||||
blocking_mode,
|
||||
blocking_ipv4,
|
||||
blocking_ipv6,
|
||||
|
||||
@@ -137,6 +137,22 @@ const Examples = (props) => (
|
||||
example_upstream_reserved
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<code>[/example.local/]94.140.14.140 2a10:50c0::1:ff</code>: <Trans
|
||||
components={[
|
||||
<a
|
||||
href="https://github.com/AdguardTeam/AdGuardHome/wiki/Configuration#upstreams-for-domains"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
key="0"
|
||||
>
|
||||
Link
|
||||
</a>,
|
||||
]}
|
||||
>
|
||||
example_multiple_upstreams_reserved
|
||||
</Trans>
|
||||
</li>
|
||||
<li>
|
||||
<code>{COMMENT_LINE_DEFAULT_TOKEN} comment</code>: <Trans>
|
||||
example_upstream_comment
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0.6rem 1.5rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.card-subtitle {
|
||||
@@ -19,8 +20,16 @@
|
||||
max-height: 17.5rem;
|
||||
}
|
||||
|
||||
.dashboard .card-table {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.dashboard .card-table-overflow--limited {
|
||||
max-height: 18rem;
|
||||
max-height: 292px;
|
||||
}
|
||||
|
||||
.dashboard .ReactTable .rt-tr-group {
|
||||
min-height: 52px;
|
||||
}
|
||||
|
||||
.card-actions {
|
||||
@@ -125,7 +134,7 @@
|
||||
|
||||
@media (min-width: 992px) {
|
||||
.dashboard .card:not(.card--full) {
|
||||
height: 22rem;
|
||||
height: 360px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,3 +149,7 @@
|
||||
.card .logs__row--blue {
|
||||
background-color: #ecf7ff;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .card .logs__row--blue {
|
||||
background-color: var(--logs__row--blue-bgcolor);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,13 @@
|
||||
height: var(--size);
|
||||
}
|
||||
|
||||
.icon--15 {
|
||||
--size: 0.95rem;
|
||||
|
||||
width: var(--size);
|
||||
height: var(--size);
|
||||
}
|
||||
|
||||
.icon--gray {
|
||||
color: var(--gray-a5);
|
||||
}
|
||||
|
||||
@@ -239,6 +239,12 @@ const Icons = () => (
|
||||
<circle cx="12" cy="12" r="9" />
|
||||
<path d="M16.1215 12.1213H11.8789V7.87866" />
|
||||
</symbol>
|
||||
|
||||
<symbol id="bullets" width="24" height="24" viewBox="0 0 24 24">
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12 7C11.1716 7 10.5 6.32843 10.5 5.5C10.5 4.67157 11.1716 4 12 4C12.8284 4 13.5 4.67157 13.5 5.5C13.5 6.32843 12.8284 7 12 7Z" fill="currentColor" />
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12 13.5C11.1716 13.5 10.5 12.8284 10.5 12C10.5 11.1716 11.1716 10.5 12 10.5C12.8284 10.5 13.5 11.1716 13.5 12C13.5 12.8284 12.8284 13.5 12 13.5Z" fill="currentColor" />
|
||||
<path fillRule="evenodd" clipRule="evenodd" d="M12 20C11.1716 20 10.5 19.3284 10.5 18.5C10.5 17.6716 11.1716 17 12 17C12.8284 17 13.5 17.6716 13.5 18.5C13.5 19.3284 12.8284 20 12 20Z" fill="currentColor" />
|
||||
</symbol>
|
||||
</svg>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import React from 'react';
|
||||
import { ResponsiveLine } from '@nivo/line';
|
||||
import addDays from 'date-fns/add_days';
|
||||
import addHours from 'date-fns/add_hours';
|
||||
import subDays from 'date-fns/sub_days';
|
||||
import subHours from 'date-fns/sub_hours';
|
||||
import dateFormat from 'date-fns/format';
|
||||
@@ -9,12 +8,14 @@ import round from 'lodash/round';
|
||||
import { useSelector } from 'react-redux';
|
||||
import PropTypes from 'prop-types';
|
||||
import './Line.css';
|
||||
import { msToDays } from '../../helpers/helpers';
|
||||
import { msToDays, msToHours } from '../../helpers/helpers';
|
||||
import { TIME_UNITS } from '../../helpers/constants';
|
||||
|
||||
const Line = ({
|
||||
data, color = 'black',
|
||||
}) => {
|
||||
const interval = msToDays(useSelector((state) => state.stats.interval));
|
||||
const interval = useSelector((state) => state.stats.interval);
|
||||
const timeUnits = useSelector((state) => state.stats.timeUnits);
|
||||
|
||||
return <ResponsiveLine
|
||||
enableArea
|
||||
@@ -44,12 +45,12 @@ const Line = ({
|
||||
enableGridY={false}
|
||||
enablePoints={false}
|
||||
xFormat={(x) => {
|
||||
if (interval >= 0 && interval <= 7) {
|
||||
const hoursAgo = subHours(Date.now(), 24 * interval);
|
||||
return dateFormat(addHours(hoursAgo, x), 'D MMM HH:00');
|
||||
if (timeUnits === TIME_UNITS.HOURS) {
|
||||
const hoursAgo = msToHours(interval) - x - 1;
|
||||
return dateFormat(subHours(Date.now(), hoursAgo), 'D MMM HH:00');
|
||||
}
|
||||
|
||||
const daysAgo = subDays(Date.now(), interval - 1);
|
||||
const daysAgo = subDays(Date.now(), msToDays(interval) - 1);
|
||||
return dateFormat(addDays(daysAgo, x), 'D MMM YYYY');
|
||||
}}
|
||||
yFormat={(y) => round(y, 2)}
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ReactTable .rt-tbody {
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.ReactTable .rt-noData {
|
||||
color: var(--rt-nodata-color);
|
||||
background-color: var(--rt-nodata-bgcolor);
|
||||
|
||||
@@ -21,6 +21,7 @@ const Tooltip = ({
|
||||
delayShow = SHOW_TOOLTIP_DELAY,
|
||||
delayHide = HIDE_TOOLTIP_DELAY,
|
||||
onVisibilityChange,
|
||||
defaultTooltipShown,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const touchEventsAvailable = 'ontouchstart' in window;
|
||||
@@ -75,6 +76,7 @@ const Tooltip = ({
|
||||
delayShow={delayShowValue}
|
||||
tooltip={renderTooltip}
|
||||
onVisibilityChange={onVisibilityChange}
|
||||
defaultTooltipShown={defaultTooltipShown}
|
||||
>
|
||||
{renderTrigger}
|
||||
</TooltipTrigger>
|
||||
@@ -97,6 +99,7 @@ Tooltip.propTypes = {
|
||||
className: propTypes.string,
|
||||
triggerClass: propTypes.string,
|
||||
onVisibilityChange: propTypes.func,
|
||||
defaultTooltipShown: propTypes.bool,
|
||||
};
|
||||
|
||||
export default Tooltip;
|
||||
|
||||
@@ -26,6 +26,10 @@ export const R_WIN_ABSOLUTE_PATH = /^([a-zA-Z]:)?(\\|\/)(?:[^\\/:*?"<>|\x00]+\\)
|
||||
|
||||
export const R_CLIENT_ID = /^[a-z0-9-]{1,63}$/;
|
||||
|
||||
export const R_IPV4_SUBNET = /^([0-9]|[1-2][0-9]|3[0-2])?$/;
|
||||
|
||||
export const R_IPV6_SUBNET = /^([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])?$/;
|
||||
|
||||
export const MIN_PASSWORD_LENGTH = 8;
|
||||
export const MAX_PASSWORD_LENGTH = 72;
|
||||
|
||||
@@ -554,3 +558,12 @@ export const DISABLE_PROTECTION_TIMINGS = {
|
||||
};
|
||||
|
||||
export const LOCAL_TIMEZONE_VALUE = 'Local';
|
||||
|
||||
export const TABLES_MIN_ROWS = 5;
|
||||
|
||||
export const DASHBOARD_TABLES_DEFAULT_PAGE_SIZE = 100;
|
||||
|
||||
export const TIME_UNITS = {
|
||||
HOURS: 'hours',
|
||||
DAYS: 'days',
|
||||
};
|
||||
|
||||
@@ -190,6 +190,12 @@ export default {
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists#piracy",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_46.txt"
|
||||
},
|
||||
"hagezi_encrypted_dns_vpn_tor_proxy_bypass": {
|
||||
"name": "HaGeZi's Encrypted DNS/VPN/TOR/Proxy Bypass",
|
||||
"categoryId": "security",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists#bypass",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_52.txt"
|
||||
},
|
||||
"hagezi_gambling_blocklist": {
|
||||
"name": "HaGeZi's Gambling Blocklist",
|
||||
"categoryId": "other",
|
||||
@@ -202,12 +208,30 @@ export default {
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_34.txt"
|
||||
},
|
||||
"hagezi_pro": {
|
||||
"name": "HaGeZi's Pro Blocklist",
|
||||
"categoryId": "general",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_48.txt"
|
||||
},
|
||||
"hagezi_pro++": {
|
||||
"name": "HaGeZi's Pro++ Blocklist",
|
||||
"categoryId": "general",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_51.txt"
|
||||
},
|
||||
"hagezi_threat_intelligence_feeds": {
|
||||
"name": "HaGeZi's Threat Intelligence Feeds",
|
||||
"categoryId": "security",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_44.txt"
|
||||
},
|
||||
"hagezi_ultimate": {
|
||||
"name": "HaGeZi's Ultimate Blocklist",
|
||||
"categoryId": "general",
|
||||
"homepage": "https://github.com/hagezi/dns-blocklists",
|
||||
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_49.txt"
|
||||
},
|
||||
"no_google": {
|
||||
"name": "No Google",
|
||||
"categoryId": "other",
|
||||
|
||||
@@ -43,7 +43,7 @@ export const renderFormattedClientCell = (value, info, isDetailed = false, isLog
|
||||
const whoisAvailable = whois_info && Object.keys(whois_info).length > 0;
|
||||
|
||||
if (name) {
|
||||
const nameValue = <div className="logs__text logs__text--link logs__text--nowrap" title={`${name} (${value})`}>
|
||||
const nameValue = <div className="logs__text logs__text--link logs__text--nowrap logs__text--client" title={`${name} (${value})`}>
|
||||
{name} <small>{`(${value})`}</small>
|
||||
</div>;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"timeUpdated": "2023-10-08T00:09:45.691Z",
|
||||
"timeUpdated": "2023-11-10T12:55:56.663Z",
|
||||
"categories": {
|
||||
"0": "audio_video_player",
|
||||
"1": "comments",
|
||||
@@ -243,7 +243,7 @@
|
||||
"name": "Australian Broadcasting Corporation",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.abc.net.au/",
|
||||
"companyId": "abc",
|
||||
"companyId": "australian_government",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"ablida": {
|
||||
@@ -681,8 +681,9 @@
|
||||
"adcolony": {
|
||||
"name": "AdColony",
|
||||
"categoryId": 4,
|
||||
"url": "thttp://www.admarvel.com/",
|
||||
"companyId": "adcolony"
|
||||
"url": "https://www.adcolony.com/history-of-adcolony/",
|
||||
"companyId": "digital_turbine",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adconion": {
|
||||
"name": "Adconion",
|
||||
@@ -1294,6 +1295,13 @@
|
||||
"url": "http://www.demdex.com/",
|
||||
"companyId": "adobe"
|
||||
},
|
||||
"adobe_developer": {
|
||||
"name": "Adobe Developer",
|
||||
"categoryId": 8,
|
||||
"url": "https://developer.adobe.com/",
|
||||
"companyId": "adobe",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adobe_dynamic_media": {
|
||||
"name": "Adobe Dynamic Media",
|
||||
"categoryId": 4,
|
||||
@@ -1309,8 +1317,9 @@
|
||||
"adobe_experience_cloud": {
|
||||
"name": "Adobe Experience Cloud",
|
||||
"categoryId": 6,
|
||||
"url": "https://www.adobe.com/experience-cloud.html",
|
||||
"companyId": "adobe"
|
||||
"url": "https://business.adobe.com/",
|
||||
"companyId": "adobe",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"adobe_login": {
|
||||
"name": "Adobe Login",
|
||||
@@ -3593,6 +3602,13 @@
|
||||
"url": null,
|
||||
"companyId": null
|
||||
},
|
||||
"bom": {
|
||||
"name": "Bureau of Meteorology",
|
||||
"categoryId": 9,
|
||||
"url": "http://bom.gov.au/",
|
||||
"companyId": "australian_government",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"bombora": {
|
||||
"name": "Bombora",
|
||||
"categoryId": 6,
|
||||
@@ -4346,6 +4362,13 @@
|
||||
"url": "http://chartbeat.com/",
|
||||
"companyId": "chartbeat"
|
||||
},
|
||||
"chartboost": {
|
||||
"name": "Chartboost",
|
||||
"categoryId": 4,
|
||||
"url": "http://chartboost.com/",
|
||||
"companyId": "take-two",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"chaser": {
|
||||
"name": "Chaser",
|
||||
"categoryId": 2,
|
||||
@@ -5943,6 +5966,20 @@
|
||||
"url": "https://discordapp.com/",
|
||||
"companyId": null
|
||||
},
|
||||
"disneyplus": {
|
||||
"name": "Disney+",
|
||||
"categoryId": 0,
|
||||
"url": "https://www.disneyplus.com/",
|
||||
"companyId": "disney",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"disneystreaming": {
|
||||
"name": "Disney Streaming",
|
||||
"categoryId": 0,
|
||||
"url": "https://press.disneyplus.com",
|
||||
"companyId": "disney",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"display_block": {
|
||||
"name": "display block",
|
||||
"categoryId": 4,
|
||||
@@ -6160,6 +6197,13 @@
|
||||
"url": "http://www.drawbrid.ge/",
|
||||
"companyId": "drawbridge"
|
||||
},
|
||||
"dreame_tech": {
|
||||
"name": "Dreame Technology",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.dreame.tech/",
|
||||
"companyId": "xiaomi",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"dreamlab.pl": {
|
||||
"name": "DreamLab.pl",
|
||||
"categoryId": 4,
|
||||
@@ -7302,7 +7346,7 @@
|
||||
"name": "Flurry",
|
||||
"categoryId": 101,
|
||||
"url": "http://www.flurry.com/",
|
||||
"companyId": "verizon",
|
||||
"companyId": "apollo_global_management",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"flxone": {
|
||||
@@ -10372,7 +10416,7 @@
|
||||
"name": "Let's Encrypt",
|
||||
"categoryId": 5,
|
||||
"url": "https://letsencrypt.org/",
|
||||
"companyId": "lets_encrypt",
|
||||
"companyId": "isrg",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"letv": {
|
||||
@@ -12358,6 +12402,13 @@
|
||||
"url": "http://www.nimblecommerce.com/",
|
||||
"companyId": "nimblecommerce"
|
||||
},
|
||||
"nine_direct_digital": {
|
||||
"name": "Nine Digital Direct",
|
||||
"categoryId": 4,
|
||||
"url": "https://ninedigitaldirect.com.au/",
|
||||
"companyId": "nine_entertainment",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"ninja_access_analysis": {
|
||||
"name": "Ninja Access Analysis",
|
||||
"categoryId": 6,
|
||||
@@ -19444,6 +19495,13 @@
|
||||
"companyId": "xhamster",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"xiaomi": {
|
||||
"name": "Xiaomi",
|
||||
"categoryId": 8,
|
||||
"url": "https://www.mi.com/",
|
||||
"companyId": "xiaomi",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"xing": {
|
||||
"name": "Xing",
|
||||
"categoryId": 6,
|
||||
@@ -19511,8 +19569,9 @@
|
||||
"yahoo": {
|
||||
"name": "Yahoo!",
|
||||
"categoryId": 6,
|
||||
"url": "https://yahoo.com",
|
||||
"companyId": "verizon"
|
||||
"url": "https://yahoo.com/",
|
||||
"companyId": "apollo_global_management",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"yahoo_ad_exchange": {
|
||||
"name": "Yahoo! Ad Exchange",
|
||||
@@ -19526,6 +19585,13 @@
|
||||
"url": "https://developer.yahoo.com/analytics/",
|
||||
"companyId": "verizon"
|
||||
},
|
||||
"yahoo_advertising": {
|
||||
"name": "Yahoo! Advertising",
|
||||
"categoryId": 4,
|
||||
"url": "https://www.advertising.yahooinc.com/",
|
||||
"companyId": "apollo_global_management",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"yahoo_analytics": {
|
||||
"name": "Yahoo! Analytics",
|
||||
"categoryId": 6,
|
||||
@@ -19556,6 +19622,13 @@
|
||||
"url": "http://searchmarketing.yahoo.com",
|
||||
"companyId": "verizon"
|
||||
},
|
||||
"yahoo_search": {
|
||||
"name": "Yahoo! Search",
|
||||
"categoryId": 4,
|
||||
"url": "https://search.yahooinc.com/",
|
||||
"companyId": "apollo_global_management",
|
||||
"source": "AdGuard"
|
||||
},
|
||||
"yahoo_small_business": {
|
||||
"name": "Yahoo! Small Business",
|
||||
"categoryId": 4,
|
||||
@@ -20047,8 +20120,8 @@
|
||||
"2leep.com": "2leep",
|
||||
"33across.com": "33across",
|
||||
"3dstats.com": "3dstats",
|
||||
"3gppnetwork.org": "3gpp",
|
||||
"3gpp.org": "3gpp",
|
||||
"3gppnetwork.org": "3gpp",
|
||||
"4cdn.org": "4chan",
|
||||
"4finance.com": "4finance_com",
|
||||
"4wnet.com": "4w_marketplace",
|
||||
@@ -20069,7 +20142,6 @@
|
||||
"aaxads.com": "aaxads.com",
|
||||
"abtasty.com": "ab_tasty",
|
||||
"d1447tq2m68ekg.cloudfront.net": "ab_tasty",
|
||||
"abc.net.au": "abc",
|
||||
"ab.co": "abc",
|
||||
"abc-cdn.net.au": "abc",
|
||||
"abc-host.net": "abc",
|
||||
@@ -20077,6 +20149,7 @@
|
||||
"abc-prod.net.au": "abc",
|
||||
"abc-stage.net.au": "abc",
|
||||
"abc-test.net.au": "abc",
|
||||
"abc.net.au": "abc",
|
||||
"abcaustralia.net.au": "abc",
|
||||
"abcradio.net.au": "abc",
|
||||
"ablida.de": "ablida",
|
||||
@@ -20193,6 +20266,7 @@
|
||||
"ad-cloud.jp": "adcloud",
|
||||
"admarvel.s3.amazonaws.com": "adcolony",
|
||||
"ads.admarvel.com": "adcolony",
|
||||
"adcolony.com": "adcolony",
|
||||
"adrdgt.com": "adconion",
|
||||
"amgdgt.com": "adconion",
|
||||
"adcrowd.com": "adcrowd",
|
||||
@@ -20238,17 +20312,17 @@
|
||||
"adgorithms.com": "adgorithms",
|
||||
"adgoto.com": "adgoto",
|
||||
"adguard.com": "adguard",
|
||||
"adtidy.org": "adguard",
|
||||
"agrd.io": "adguard",
|
||||
"adguard.app": "adguard",
|
||||
"adguard.info": "adguard",
|
||||
"adguard.io": "adguard",
|
||||
"adguard.org": "adguard",
|
||||
"adtidy.org": "adguard",
|
||||
"agrd.io": "adguard",
|
||||
"adguard-dns.com": "adguard_dns",
|
||||
"adguard-dns.io": "adguard_dns",
|
||||
"adguardvpn.com": "adguard_vpn",
|
||||
"adguard-vpn.com": "adguard_vpn",
|
||||
"adguard-vpn.online": "adguard_vpn",
|
||||
"adguardvpn.com": "adguard_vpn",
|
||||
"adhands.ru": "adhands",
|
||||
"adhese.be": "adhese",
|
||||
"adhese.com": "adhese",
|
||||
@@ -20264,9 +20338,9 @@
|
||||
"cdn.adjs.net": "adjs",
|
||||
"adjug.com": "adjug",
|
||||
"adjust.com": "adjust",
|
||||
"adjust.net.in": "adjust",
|
||||
"adj.st": "adjust",
|
||||
"adjust.io": "adjust",
|
||||
"adjust.net.in": "adjust",
|
||||
"adjust.world": "adjust",
|
||||
"apptrace.com": "adjust",
|
||||
"adk2.com": "adk2",
|
||||
@@ -20347,6 +20421,7 @@
|
||||
"demdex.net": "adobe_audience_manager",
|
||||
"everestjs.net": "adobe_audience_manager",
|
||||
"everesttech.net": "adobe_audience_manager",
|
||||
"adobe.io": "adobe_developer",
|
||||
"scene7.com": "adobe_dynamic_media",
|
||||
"adobedtm.com": "adobe_dynamic_tag_management",
|
||||
"2o7.net": "adobe_experience_cloud",
|
||||
@@ -20616,18 +20691,21 @@
|
||||
"amazon.fr": "amazon",
|
||||
"amazon.it": "amazon",
|
||||
"d3io1k5o0zdpqr.cloudfront.net": "amazon",
|
||||
"amazoncrl.com": "amazon",
|
||||
"aamazoncognito.com": "amazon",
|
||||
"amazonbrowserapp.es": "amazon",
|
||||
"amazonbrowserapp.co.uk": "amazon",
|
||||
"amazon.sa": "amazon",
|
||||
"amazon.nl": "amazon",
|
||||
"amazon.in": "amazon",
|
||||
"amazon.com.mx": "amazon",
|
||||
"amazon.com.au": "amazon",
|
||||
"amazon-corp.com": "amazon",
|
||||
"a2z.com": "amazon",
|
||||
"aamazoncognito.com": "amazon",
|
||||
"amazon-corp.com": "amazon",
|
||||
"amazon-dss.com": "amazon",
|
||||
"amazon.com.au": "amazon",
|
||||
"amazon.com.mx": "amazon",
|
||||
"amazon.dev": "amazon",
|
||||
"amazon.in": "amazon",
|
||||
"amazon.nl": "amazon",
|
||||
"amazon.sa": "amazon",
|
||||
"amazonbrowserapp.co.uk": "amazon",
|
||||
"amazonbrowserapp.es": "amazon",
|
||||
"amazoncrl.com": "amazon",
|
||||
"firetvcaptiveportal.com": "amazon",
|
||||
"ntp-fireos.com": "amazon",
|
||||
"amazon-adsystem.com": "amazon_adsystem",
|
||||
"serving-sys.com": "amazon_adsystem",
|
||||
"sizmek.com": "amazon_adsystem",
|
||||
@@ -20643,12 +20721,16 @@
|
||||
"amazontrust.com": "amazon_cdn",
|
||||
"associates-amazon.com": "amazon_cdn",
|
||||
"cloudfront.net": "amazon_cloudfront",
|
||||
"ota-cloudfront.net": "amazon_cloudfront",
|
||||
"axx-eu.amazon-adsystem.com": "amazon_mobile_ads",
|
||||
"amazonpay.com": "amazon_payments",
|
||||
"payments-amazon.com": "amazon_payments",
|
||||
"amazonpay.in": "amazon_payments",
|
||||
"aiv-cdn.net": "amazon_video",
|
||||
"aiv-delivery.net": "amazon_video",
|
||||
"amazonvideo.com": "amazon_video",
|
||||
"pv-cdn.net": "amazon_video",
|
||||
"primevideo.com": "amazon_video",
|
||||
"amazonaws.com": "amazon_web_services",
|
||||
"amazonwebservices.com": "amazon_web_services",
|
||||
"awsstatic.com": "amazon_web_services",
|
||||
@@ -20692,31 +20774,32 @@
|
||||
"eum-appdynamics.com": "appdynamics",
|
||||
"jscdn.appier.net": "appier",
|
||||
"apple.com": "apple",
|
||||
"me.com": "apple",
|
||||
"apple.news": "apple",
|
||||
"apple-dns.net": "apple",
|
||||
"aaplimg.com": "apple",
|
||||
"icloud.com": "apple",
|
||||
"itunes.com": "apple",
|
||||
"icloud-content.com": "apple",
|
||||
"mzstatic.com": "apple",
|
||||
"cdn-apple.com": "apple",
|
||||
"apple-mapkit.com": "apple",
|
||||
"icons.axm-usercontent-apple.com": "apple",
|
||||
"apple-cloudkit.com": "apple",
|
||||
"apzones.com": "apple",
|
||||
"apple-dns.net": "apple",
|
||||
"apple-livephotoskit.com": "apple",
|
||||
"apple-mapkit.com": "apple",
|
||||
"apple.news": "apple",
|
||||
"apzones.com": "apple",
|
||||
"cdn-apple.com": "apple",
|
||||
"icloud-content.com": "apple",
|
||||
"icloud.com": "apple",
|
||||
"icons.axm-usercontent-apple.com": "apple",
|
||||
"itunes.com": "apple",
|
||||
"me.com": "apple",
|
||||
"mzstatic.com": "apple",
|
||||
"safebrowsing.apple": "apple",
|
||||
"safebrowsing.g.applimg.com": "apple",
|
||||
"iadsdk.apple.com": "apple_ads",
|
||||
"applifier.com": "applifier",
|
||||
"assets.applovin.com": "applovin",
|
||||
"applvn.com": "applovin",
|
||||
"applovin.com": "applovin",
|
||||
"applvn.com": "applovin",
|
||||
"appmetrx.com": "appmetrx",
|
||||
"adnxs.com": "appnexus",
|
||||
"adnxs.net": "appnexus",
|
||||
"appsflyer.com": "appsflyer",
|
||||
"appsflyersdk.com": "appsflyer",
|
||||
"adne.tv": "apptv",
|
||||
"readserver.net": "apptv",
|
||||
"www.apture.com": "apture",
|
||||
@@ -20794,6 +20877,8 @@
|
||||
"ad.globe7.com": "axill",
|
||||
"azadify.com": "azadify",
|
||||
"azure.com": "azure",
|
||||
"azure.net": "azure",
|
||||
"azurefd.net": "azure",
|
||||
"trafficmanager.net": "azure",
|
||||
"blob.core.windows.net": "azure_blob_storage",
|
||||
"azureedge.net": "azureedge.net",
|
||||
@@ -20926,6 +21011,7 @@
|
||||
"secure.apps.shappify.com": "bold",
|
||||
"boldchat.com": "boldchat",
|
||||
"boltdns.net": "boltdns.net",
|
||||
"bom.gov.au": "bom",
|
||||
"ml314.com": "bombora",
|
||||
"bongacams.com": "bongacams.com",
|
||||
"bonial.com": "bonial",
|
||||
@@ -21083,6 +21169,7 @@
|
||||
"chaordicsystems.com": "chaordic",
|
||||
"chartbeat.com": "chartbeat",
|
||||
"chartbeat.net": "chartbeat",
|
||||
"chartboost.com": "chartboost",
|
||||
"chaser.ru": "chaser",
|
||||
"cloud.chatbeacon.io": "chat_beacon",
|
||||
"chatango.com": "chatango",
|
||||
@@ -21170,8 +21257,8 @@
|
||||
"cloud-media.fr": "cloud-media.fr",
|
||||
"cloudflare.com": "cloudflare",
|
||||
"cloudflare.net": "cloudflare",
|
||||
"cloudflare-dns.com": "cloudflare",
|
||||
"cloudflare-dm-cmpimg.com": "cloudflare",
|
||||
"cloudflare-dns.com": "cloudflare",
|
||||
"cloudflare-ipfs.com": "cloudflare",
|
||||
"cloudflare-quic.com": "cloudflare",
|
||||
"cloudflare-terms-of-service-abuse.com": "cloudflare",
|
||||
@@ -21184,8 +21271,10 @@
|
||||
"cloudflareresolve.com": "cloudflare",
|
||||
"cloudflaressl.com": "cloudflare",
|
||||
"cloudflarestatus.com": "cloudflare",
|
||||
"cloudflarestream.com": "cloudflare",
|
||||
"pacloudflare.com": "cloudflare",
|
||||
"sn-cloudflare.com": "cloudflare",
|
||||
"videodelivery.net": "cloudflare",
|
||||
"cloudimg.io": "cloudimage.io",
|
||||
"cloudinary.com": "cloudinary",
|
||||
"clovenetwork.com": "clove_network",
|
||||
@@ -21454,6 +21543,10 @@
|
||||
"directadvert.ru": "directadvert",
|
||||
"directrev.com": "directrev",
|
||||
"discordapp.com": "discord",
|
||||
"disneyplus.com": "disneyplus",
|
||||
"bamgrid.com": "disneystreaming",
|
||||
"dssedge.com": "disneystreaming",
|
||||
"dssott.com": "disneystreaming",
|
||||
"d81mfvml8p5ml.cloudfront.net": "display_block",
|
||||
"disqus.com": "disqus",
|
||||
"disquscdn.com": "disqus",
|
||||
@@ -21497,6 +21590,8 @@
|
||||
"doubleverify.com": "doubleverify",
|
||||
"wrating.com": "dratio",
|
||||
"adsymptotic.com": "drawbridge",
|
||||
"dreame.tech": "dreame_tech",
|
||||
"dreametech.com": "dreame_tech",
|
||||
"dreamlab.pl": "dreamlab.pl",
|
||||
"drift.com": "drift",
|
||||
"js.driftt.com": "drift",
|
||||
@@ -21717,18 +21812,18 @@
|
||||
"findologic.com": "findologic.com",
|
||||
"app-measurement.com": "firebase",
|
||||
"fcm.googleapis.com": "firebase",
|
||||
"firebaseappcheck.googleapis.com": "firebase",
|
||||
"firebaseapp.com": "firebase",
|
||||
"firebase.com": "firebase",
|
||||
"firebasedynamiclinks.googleapis.com": "firebase",
|
||||
"firebase.google.com": "firebase",
|
||||
"firebase.googleapis.com": "firebase",
|
||||
"firebaseapp.com": "firebase",
|
||||
"firebaseappcheck.googleapis.com": "firebase",
|
||||
"firebasedynamiclinks-ipv4.googleapis.com": "firebase",
|
||||
"firebasedynamiclinks-ipv6.googleapis.com": "firebase",
|
||||
"firebase.googleapis.com": "firebase",
|
||||
"firebase.google.com": "firebase",
|
||||
"firebasedynamiclinks.googleapis.com": "firebase",
|
||||
"firebaseinappmessaging.googleapis.com": "firebase",
|
||||
"firebaseinstallations.googleapis.com": "firebase",
|
||||
"firebaselogging.googleapis.com": "firebase",
|
||||
"firebaselogging-pa.googleapis.com": "firebase",
|
||||
"firebaselogging.googleapis.com": "firebase",
|
||||
"firebaseperusertopics-pa.googleapis.com": "firebase",
|
||||
"firebaseremoteconfig.googleapis.com": "firebase",
|
||||
"firebaseio.com": "firebaseio.com",
|
||||
@@ -21806,9 +21901,9 @@
|
||||
"freegeoip.net": "freegeoip_net",
|
||||
"freenet.de": "freenet_de",
|
||||
"freent.de": "freenet_de",
|
||||
"freeviewaustralia.tv": "freeview",
|
||||
"freeview.com.au": "freeview",
|
||||
"freeview.com": "freeview",
|
||||
"freeview.com.au": "freeview",
|
||||
"freeviewaustralia.tv": "freeview",
|
||||
"fwmrm.net": "freewheel",
|
||||
"heimdall.fresh8.co": "fresh8",
|
||||
"d36mpcpuzc4ztk.cloudfront.net": "freshdesk",
|
||||
@@ -21884,7 +21979,9 @@
|
||||
"githubassets.com": "github",
|
||||
"githubusercontent.com": "github",
|
||||
"ghcr.io": "github",
|
||||
"github.blog": "github",
|
||||
"github.dev": "github",
|
||||
"octocaptcha.com": "github",
|
||||
"githubapp.com": "github_apps",
|
||||
"github.io": "github_pages",
|
||||
"aff3.gittigidiyor.com": "gittigidiyor_affiliate_program",
|
||||
@@ -21958,7 +22055,6 @@
|
||||
"google.ae": "google",
|
||||
"google.al": "google",
|
||||
"google.am": "google",
|
||||
"googleapis.cn": "google",
|
||||
"google.as": "google",
|
||||
"google.az": "google",
|
||||
"google.ba": "google",
|
||||
@@ -21981,11 +22077,20 @@
|
||||
"google.co.bw": "google",
|
||||
"google.co.ck": "google",
|
||||
"google.co.cr": "google",
|
||||
"googlecode.com": "google",
|
||||
"google.co.il": "google",
|
||||
"google.co.ke": "google",
|
||||
"google.co.kr": "google",
|
||||
"google.co.ls": "google",
|
||||
"google.co.mz": "google",
|
||||
"google.co.nz": "google",
|
||||
"google.co.tz": "google",
|
||||
"google.co.ug": "google",
|
||||
"google.co.uz": "google",
|
||||
"google.co.ve": "google",
|
||||
"google.co.vi": "google",
|
||||
"google.co.za": "google",
|
||||
"google.co.zm": "google",
|
||||
"google.co.zw": "google",
|
||||
"google.com.af": "google",
|
||||
"google.com.ag": "google",
|
||||
"google.com.ai": "google",
|
||||
@@ -22033,20 +22138,9 @@
|
||||
"google.com.uy": "google",
|
||||
"google.com.vc": "google",
|
||||
"google.com.vn": "google",
|
||||
"google.co.mz": "google",
|
||||
"google.co.nz": "google",
|
||||
"google.co.tz": "google",
|
||||
"google.co.ug": "google",
|
||||
"google.co.uz": "google",
|
||||
"google.co.ve": "google",
|
||||
"google.co.vi": "google",
|
||||
"google.co.za": "google",
|
||||
"google.co.zm": "google",
|
||||
"google.co.zw": "google",
|
||||
"google.cv": "google",
|
||||
"google.dj": "google",
|
||||
"google.dm": "google",
|
||||
"googledownloads.cn": "google",
|
||||
"google.ee": "google",
|
||||
"google.fm": "google",
|
||||
"google.ga": "google",
|
||||
@@ -22088,7 +22182,6 @@
|
||||
"google.net": "google",
|
||||
"google.nr": "google",
|
||||
"google.nu": "google",
|
||||
"googleoptimize.com": "google",
|
||||
"google.org": "google",
|
||||
"google.pn": "google",
|
||||
"google.ps": "google",
|
||||
@@ -22112,8 +22205,12 @@
|
||||
"google.us": "google",
|
||||
"google.vg": "google",
|
||||
"google.vu": "google",
|
||||
"googleweblight.in": "google",
|
||||
"google.ws": "google",
|
||||
"googleapis.cn": "google",
|
||||
"googlecode.com": "google",
|
||||
"googledownloads.cn": "google",
|
||||
"googleoptimize.com": "google",
|
||||
"googleweblight.in": "google",
|
||||
"googlezip.net": "google",
|
||||
"gstatic.cn": "google",
|
||||
"news.google.com": "google",
|
||||
@@ -22140,10 +22237,10 @@
|
||||
"alt7-mtalk.google.com": "google_chat",
|
||||
"alt8-mtalk.google.com": "google_chat",
|
||||
"chat.google.com": "google_chat",
|
||||
"mobile-gtalk4.l.google.com": "google_chat",
|
||||
"mobile-gtalk.l.google.com": "google_chat",
|
||||
"mtalk4.google.com": "google_chat",
|
||||
"mobile-gtalk4.l.google.com": "google_chat",
|
||||
"mtalk.google.com": "google_chat",
|
||||
"mtalk4.google.com": "google_chat",
|
||||
"talk.google.com": "google_chat",
|
||||
"talk.l.google.com": "google_chat",
|
||||
"talkx.l.google.com": "google_chat",
|
||||
@@ -22163,10 +22260,10 @@
|
||||
"mail-ads.google.com": "google_email",
|
||||
"fonts.googleapis.com": "google_fonts",
|
||||
"cloudfunctions.net": "google_hosted",
|
||||
"ghs46.googlehosted.com": "google_hosted",
|
||||
"ghs4.googlehosted.com": "google_hosted",
|
||||
"ghs6.googlehosted.com": "google_hosted",
|
||||
"ghs.googlehosted.com": "google_hosted",
|
||||
"ghs4.googlehosted.com": "google_hosted",
|
||||
"ghs46.googlehosted.com": "google_hosted",
|
||||
"ghs6.googlehosted.com": "google_hosted",
|
||||
"googlehosted.l.googleusercontent.com": "google_hosted",
|
||||
"run.app": "google_hosted",
|
||||
"supl.google.com": "google_location",
|
||||
@@ -22180,9 +22277,9 @@
|
||||
"maps.google.ca": "google_maps",
|
||||
"maps.google.ch": "google_maps",
|
||||
"maps.google.co.jp": "google_maps",
|
||||
"maps.google.co.uk": "google_maps",
|
||||
"maps.google.com": "google_maps",
|
||||
"maps.google.com.mx": "google_maps",
|
||||
"maps.google.co.uk": "google_maps",
|
||||
"maps.google.es": "google_maps",
|
||||
"maps.google.se": "google_maps",
|
||||
"maps.gstatic.com": "google_maps",
|
||||
@@ -22190,6 +22287,8 @@
|
||||
"adservice.google.ca": "google_marketing",
|
||||
"adservice.google.co.in": "google_marketing",
|
||||
"adservice.google.co.kr": "google_marketing",
|
||||
"adservice.google.co.uk": "google_marketing",
|
||||
"adservice.google.co.za": "google_marketing",
|
||||
"adservice.google.com": "google_marketing",
|
||||
"adservice.google.com.ar": "google_marketing",
|
||||
"adservice.google.com.au": "google_marketing",
|
||||
@@ -22203,8 +22302,6 @@
|
||||
"adservice.google.com.tr": "google_marketing",
|
||||
"adservice.google.com.tw": "google_marketing",
|
||||
"adservice.google.com.vn": "google_marketing",
|
||||
"adservice.google.co.uk": "google_marketing",
|
||||
"adservice.google.co.za": "google_marketing",
|
||||
"adservice.google.de": "google_marketing",
|
||||
"adservice.google.dk": "google_marketing",
|
||||
"adservice.google.es": "google_marketing",
|
||||
@@ -22219,17 +22316,17 @@
|
||||
"googlesyndication-cn.com": "google_marketing",
|
||||
"duo.google.com": "google_meet",
|
||||
"hangouts.clients6.google.com": "google_meet",
|
||||
"hangouts.googleapis.com": "google_meet",
|
||||
"hangouts.google.com": "google_meet",
|
||||
"hangouts.googleapis.com": "google_meet",
|
||||
"meet.google.com": "google_meet",
|
||||
"meetings.googleapis.com": "google_meet",
|
||||
"stun1.l.google.com": "google_meet",
|
||||
"stun.l.google.com": "google_meet",
|
||||
"stun1.l.google.com": "google_meet",
|
||||
"ggpht.com": "google_photos",
|
||||
"play-fe.googleapis.com": "google_play",
|
||||
"play.googleapis.com": "google_play",
|
||||
"play.google.com": "google_play",
|
||||
"play-lh.googleusercontent.com": "google_play",
|
||||
"play.google.com": "google_play",
|
||||
"play.googleapis.com": "google_play",
|
||||
"1e100cdn.net": "google_servers",
|
||||
"gvt1.com": "google_servers",
|
||||
"gvt2.com": "google_servers",
|
||||
@@ -22531,9 +22628,9 @@
|
||||
"iprom.net": "iprom",
|
||||
"ipromote.com": "ipromote",
|
||||
"clickmanage.com": "iprospect",
|
||||
"qy.net": "iqiyi",
|
||||
"iqiyi.com": "iqiyi",
|
||||
"iq.com": "iqiyi",
|
||||
"iqiyi.com": "iqiyi",
|
||||
"qy.net": "iqiyi",
|
||||
"addelive.com": "ironsource",
|
||||
"afdads.com": "ironsource",
|
||||
"delivery47.com": "ironsource",
|
||||
@@ -22772,11 +22869,11 @@
|
||||
"footprint.net": "level3_communications",
|
||||
"alphonso.tv": "lgads",
|
||||
"lgads.tv": "lgads",
|
||||
"lg.com": "lgtv",
|
||||
"lge.com": "lgtv",
|
||||
"lgsmartad.com": "lgtv",
|
||||
"lgtvcommon.com": "lgtv",
|
||||
"lgtvsdp.com": "lgtv",
|
||||
"lge.com": "lgtv",
|
||||
"lg.com": "lgtv",
|
||||
"licensebuttons.net": "licensebuttons.net",
|
||||
"lfstmedia.com": "lifestreet_media",
|
||||
"content-recommendation.net": "ligatus",
|
||||
@@ -22971,8 +23068,8 @@
|
||||
"s1.mediaad.org": "mediaad",
|
||||
"mlnadvertising.com": "mediaglu",
|
||||
"fhserve.com": "mediahub",
|
||||
"medialab.la": "medialab",
|
||||
"media-lab.ai": "medialab",
|
||||
"medialab.la": "medialab",
|
||||
"adnet.ru": "medialand",
|
||||
"medialand.ru": "medialand",
|
||||
"medialead.de": "medialead",
|
||||
@@ -23043,7 +23140,13 @@
|
||||
"s-microsoft.com": "microsoft",
|
||||
"trouter.io": "microsoft",
|
||||
"windows.net": "microsoft",
|
||||
"bingapis.com": "microsoft",
|
||||
"msauth.net": "microsoft",
|
||||
"msftauth.net": "microsoft",
|
||||
"msftstatic.com": "microsoft",
|
||||
"msidentity.com": "microsoft",
|
||||
"nelreports.net": "microsoft",
|
||||
"windowscentral.com": "microsoft",
|
||||
"analytics.live.com": "microsoft_analytics",
|
||||
"a.clarity.ms": "microsoft_clarity",
|
||||
"b.clarity.ms": "microsoft_clarity",
|
||||
@@ -23128,6 +23231,7 @@
|
||||
"mrpdata.com": "mrpdata",
|
||||
"mrpdata.net": "mrpdata",
|
||||
"mrskincash.com": "mrskincash",
|
||||
"a-msedge.net": "msedge",
|
||||
"e-msedge.net": "msedge",
|
||||
"l-msedge.net": "msedge",
|
||||
"s-msedge.net": "msedge",
|
||||
@@ -23249,6 +23353,7 @@
|
||||
"ads.ngageinc.com": "ngage_inc.",
|
||||
"nice264.com": "nice264.com",
|
||||
"nimblecommerce.com": "nimblecommerce",
|
||||
"nineanalytics.io": "nine_direct_digital",
|
||||
"cho-chin.com": "ninja_access_analysis",
|
||||
"donburako.com": "ninja_access_analysis",
|
||||
"hishaku.com": "ninja_access_analysis",
|
||||
@@ -23352,12 +23457,12 @@
|
||||
"opinary.com": "opinary",
|
||||
"opinionbar.com": "opinionbar",
|
||||
"emagazines.com": "oplytic",
|
||||
"oppomobile.com": "oppo",
|
||||
"heytapmobi.com": "oppo",
|
||||
"heytapmobile.com": "oppo",
|
||||
"heytapdl.com": "oppo",
|
||||
"allawnos.com": "oppo",
|
||||
"allawntech.com": "oppo",
|
||||
"heytapdl.com": "oppo",
|
||||
"heytapmobi.com": "oppo",
|
||||
"heytapmobile.com": "oppo",
|
||||
"oppomobile.com": "oppo",
|
||||
"opta.net": "opta.net",
|
||||
"optaim.com": "optaim",
|
||||
"cookielaw.org": "optanaon",
|
||||
@@ -23484,8 +23589,9 @@
|
||||
"loveadvert.ru": "play_by_mamba",
|
||||
"playbuzz.com": "playbuzz.com",
|
||||
"pof.com": "plenty_of_fish",
|
||||
"plex.tv": "plex",
|
||||
"plex.bz": "plex",
|
||||
"plex.direct": "plex",
|
||||
"plex.tv": "plex",
|
||||
"analytics.plex.tv": "plex_metrics",
|
||||
"metrics.plex.tv": "plex_metrics",
|
||||
"plista.com": "plista",
|
||||
@@ -23896,6 +24002,7 @@
|
||||
"samsungsds.com": "samsungsds",
|
||||
"internetat.tv": "samsungtv",
|
||||
"samsungcloud.tv": "samsungtv",
|
||||
"tizenservice.com": "samsungtv",
|
||||
"ilsemedia.nl": "sanoma.fi",
|
||||
"sanoma.fi": "sanoma.fi",
|
||||
"d13im3ek7neeqp.cloudfront.net": "sap_crm",
|
||||
@@ -24000,12 +24107,12 @@
|
||||
"cdn.shopify.com": "shopify",
|
||||
"myshopify.com": "shopify",
|
||||
"shop.app": "shopify",
|
||||
"shopifyapps.com": "shopify",
|
||||
"shopifycdn.net": "shopify",
|
||||
"shopify.co.za": "shopify",
|
||||
"shopify.com.au": "shopify",
|
||||
"shopify.com.mx": "shopify",
|
||||
"shopify.co.za": "shopify",
|
||||
"shopify.dev": "shopify",
|
||||
"shopifyapps.com": "shopify",
|
||||
"shopifycdn.net": "shopify",
|
||||
"shopifynetwork.com": "shopify",
|
||||
"shopifypreview.com": "shopify",
|
||||
"shopifysvc.com": "shopify_stats",
|
||||
@@ -24042,8 +24149,8 @@
|
||||
"pages04.net": "silverpop",
|
||||
"pages05.net": "silverpop",
|
||||
"similardeals.net": "similardeals.net",
|
||||
"similarweb.io": "similarweb",
|
||||
"similarweb.com": "similarweb",
|
||||
"similarweb.io": "similarweb",
|
||||
"d8rk54i4mohrb.cloudfront.net": "simplereach",
|
||||
"simplereach.com": "simplereach",
|
||||
"simpli.fi": "simpli.fi",
|
||||
@@ -24082,10 +24189,10 @@
|
||||
"skypeassets.com": "skype",
|
||||
"skysa.com": "skysa",
|
||||
"skyscnr.com": "skyscnr.com",
|
||||
"slack.com": "slack",
|
||||
"slackb.com": "slack",
|
||||
"slack-edge.com": "slack",
|
||||
"slack-imgs.com": "slack",
|
||||
"slack.com": "slack",
|
||||
"slackb.com": "slack",
|
||||
"slashdot.org": "slashdot_widget",
|
||||
"sleeknotestaticcontent.sleeknote.com": "sleeknote",
|
||||
"resultspage.com": "sli_systems",
|
||||
@@ -24356,8 +24463,8 @@
|
||||
"teaser.cc": "teaser.cc",
|
||||
"emailretargeting.com": "tedemis",
|
||||
"tracking.dsmmadvantage.com": "teletech",
|
||||
"telstra.com.au": "telstra",
|
||||
"telstra.com": "telstra",
|
||||
"telstra.com.au": "telstra",
|
||||
"tenderapp.com": "tender",
|
||||
"tensitionschoo.club": "tensitionschoo.club",
|
||||
"watch.teroti.com": "teroti",
|
||||
@@ -24728,9 +24835,9 @@
|
||||
"tools.vpscash.nl": "vpscash",
|
||||
"vsassets.io": "vs",
|
||||
"exp-tas.com": "vscode",
|
||||
"vscode-unpkg.net": "vscode",
|
||||
"v0cdn.net": "vscode",
|
||||
"vscode-cdn.net": "vscode",
|
||||
"vscode-unpkg.net": "vscode",
|
||||
"vtracy.de": "vtracy.de",
|
||||
"liftoff.io": "vungle",
|
||||
"vungle.com": "vungle",
|
||||
@@ -24803,8 +24910,8 @@
|
||||
"wetter.com": "wetter_com",
|
||||
"wettercomassets.com": "wetter_com",
|
||||
"whatsbroadcast.com": "whatbroadcast",
|
||||
"whatsapp.net": "whatsapp",
|
||||
"whatsapp.com": "whatsapp",
|
||||
"whatsapp.net": "whatsapp",
|
||||
"whisper.onelink.me": "whisper",
|
||||
"whisper.sh": "whisper",
|
||||
"amung.us": "whos.amung.us",
|
||||
@@ -24876,6 +24983,13 @@
|
||||
"xhamsterlive.com": "xhamster",
|
||||
"xhamsterpremium.com": "xhamster",
|
||||
"xhcdn.com": "xhamster",
|
||||
"huami.com": "xiaomi",
|
||||
"mi-img.com": "xiaomi",
|
||||
"mi.com": "xiaomi",
|
||||
"miui.com": "xiaomi",
|
||||
"xiaomi.com": "xiaomi",
|
||||
"xiaomi.net": "xiaomi",
|
||||
"xiaomiyoupin.com": "xiaomi",
|
||||
"xing-share.com": "xing",
|
||||
"xing.com": "xing",
|
||||
"xmediaclicks.com": "xmediaclicks",
|
||||
@@ -24893,10 +25007,15 @@
|
||||
"yahoo.com": "yahoo",
|
||||
"yahooapis.com": "yahoo",
|
||||
"yimg.com": "yahoo",
|
||||
"ads.yahoo.com": "yahoo_ad_exchange",
|
||||
"oath.cloud": "yahoo",
|
||||
"yahoo.net": "yahoo",
|
||||
"yahooinc.com": "yahoo",
|
||||
"yahoodns.net": "yahoo",
|
||||
"yads.yahoo.com": "yahoo_ad_exchange",
|
||||
"yieldmanager.com": "yahoo_ad_exchange",
|
||||
"pr-bh.ybp.yahoo.com": "yahoo_ad_manager",
|
||||
"ads.yahoo.com": "yahoo_advertising",
|
||||
"adtech.yahooinc.com": "yahoo_advertising",
|
||||
"analytics.yahoo.com": "yahoo_analytics",
|
||||
"np.lexity.com": "yahoo_commerce_central",
|
||||
"storage-yahoo.jp": "yahoo_japan_retargeting",
|
||||
@@ -24906,6 +25025,7 @@
|
||||
"yjtag.jp": "yahoo_japan_retargeting",
|
||||
"ov.yahoo.co.jp": "yahoo_overture",
|
||||
"overture.com": "yahoo_overture",
|
||||
"search.yahooinc.com": "yahoo_search",
|
||||
"luminate.com": "yahoo_small_business",
|
||||
"pixazza.com": "yahoo_small_business",
|
||||
"awaps.yandex.ru": "yandex",
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
R_DOMAIN,
|
||||
MAX_PASSWORD_LENGTH,
|
||||
MIN_PASSWORD_LENGTH,
|
||||
R_IPV4_SUBNET,
|
||||
R_IPV6_SUBNET,
|
||||
} from './constants';
|
||||
import { ip4ToInt, isValidAbsolutePath } from './form';
|
||||
import { isIpInCidr, parseSubnetMask } from './helpers';
|
||||
@@ -365,3 +367,25 @@ export const validateIpGateway = (value, allValues) => {
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param value {string}
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const validateIPv4Subnet = (value) => {
|
||||
if (!R_IPV4_SUBNET.test(value)) {
|
||||
return i18next.t('rate_limit_subnet_len_ipv4_error');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param value {string}
|
||||
* @returns {Function}
|
||||
*/
|
||||
export const validateIPv6Subnet = (value) => {
|
||||
if (!R_IPV6_SUBNET.test(value)) {
|
||||
return i18next.t('rate_limit_subnet_len_ipv6_error');
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
@@ -44,6 +44,19 @@ const dashboard = handleActions(
|
||||
|
||||
return newState;
|
||||
},
|
||||
[actions.timerStatusSuccess]: (state, { payload }) => {
|
||||
const {
|
||||
protection_enabled: protectionEnabled,
|
||||
protection_disabled_duration: protectionDisabledDuration,
|
||||
} = payload;
|
||||
const newState = {
|
||||
...state,
|
||||
protectionEnabled,
|
||||
protectionDisabledDuration,
|
||||
};
|
||||
|
||||
return newState;
|
||||
},
|
||||
|
||||
[actions.getVersionRequest]: (state) => ({
|
||||
...state,
|
||||
|
||||
@@ -128,8 +128,7 @@ const dhcp = handleActions(
|
||||
const newState = {
|
||||
...state,
|
||||
isModalOpen: !state.isModalOpen,
|
||||
modalType: payload?.type || '',
|
||||
leaseModalConfig: payload?.config,
|
||||
leaseModalConfig: payload,
|
||||
};
|
||||
return newState;
|
||||
},
|
||||
|
||||
@@ -18,6 +18,7 @@ const dnsConfig = handleActions(
|
||||
fallback_dns,
|
||||
bootstrap_dns,
|
||||
local_ptr_upstreams,
|
||||
ratelimit_whitelist,
|
||||
...values
|
||||
} = payload;
|
||||
|
||||
@@ -30,6 +31,7 @@ const dnsConfig = handleActions(
|
||||
fallback_dns: (fallback_dns && fallback_dns.join('\n')) || '',
|
||||
bootstrap_dns: (bootstrap_dns && bootstrap_dns.join('\n')) || '',
|
||||
local_ptr_upstreams: (local_ptr_upstreams && local_ptr_upstreams.join('\n')) || '',
|
||||
ratelimit_whitelist: (ratelimit_whitelist && ratelimit_whitelist.join('\n')) || '',
|
||||
processingGetConfig: false,
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { handleActions } from 'redux-actions';
|
||||
import { normalizeTopClients } from '../helpers/helpers';
|
||||
import { DAY, HOUR, STATS_INTERVALS_DAYS } from '../helpers/constants';
|
||||
import {
|
||||
DAY,
|
||||
HOUR,
|
||||
STATS_INTERVALS_DAYS,
|
||||
TIME_UNITS,
|
||||
} from '../helpers/constants';
|
||||
|
||||
import * as actions from '../actions/stats';
|
||||
|
||||
@@ -18,6 +23,7 @@ const defaultStats = {
|
||||
numReplacedSafebrowsing: 0,
|
||||
numReplacedSafesearch: 0,
|
||||
avgProcessingTime: 0,
|
||||
timeUnits: TIME_UNITS.HOURS,
|
||||
};
|
||||
|
||||
const stats = handleActions(
|
||||
@@ -60,6 +66,7 @@ const stats = handleActions(
|
||||
avg_processing_time: avgProcessingTime,
|
||||
top_upstreams_responses: topUpstreamsResponses,
|
||||
top_upstrems_avg_time: topUpstreamsAvgTime,
|
||||
time_units: timeUnits,
|
||||
} = payload;
|
||||
|
||||
const newState = {
|
||||
@@ -81,6 +88,7 @@ const stats = handleActions(
|
||||
avgProcessingTime,
|
||||
topUpstreamsResponses,
|
||||
topUpstreamsAvgTime,
|
||||
timeUnits,
|
||||
};
|
||||
|
||||
return newState;
|
||||
|
||||
43
go.mod
43
go.mod
@@ -3,21 +3,21 @@ module github.com/AdguardTeam/AdGuardHome
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/AdguardTeam/dnsproxy v0.56.1
|
||||
github.com/AdguardTeam/golibs v0.17.1
|
||||
github.com/AdguardTeam/urlfilter v0.17.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/digineo/go-ipset/v2 v2.2.1
|
||||
github.com/dimfeld/httptreemux/v5 v5.5.0
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
github.com/fsnotify/fsnotify v1.7.0
|
||||
github.com/go-ping/ping v1.1.0
|
||||
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.3.1
|
||||
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a
|
||||
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,14 +27,14 @@ require (
|
||||
// own code for that. Perhaps, use gopacket.
|
||||
github.com/mdlayher/raw v0.1.0
|
||||
github.com/miekg/dns v1.1.56
|
||||
github.com/quic-go/quic-go v0.39.0
|
||||
github.com/quic-go/quic-go v0.40.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/ti-mo/netfilter v0.5.0
|
||||
go.etcd.io/bbolt v1.3.7
|
||||
golang.org/x/crypto v0.14.0
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0
|
||||
github.com/ti-mo/netfilter v0.5.1
|
||||
go.etcd.io/bbolt v1.3.8
|
||||
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.0
|
||||
@@ -47,19 +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-20230926050212-f7f687d19a98 // indirect
|
||||
github.com/mdlayher/socket v0.5.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.0 // 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.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.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.3.4 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // 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.13.0 // indirect
|
||||
golang.org/x/sync v0.4.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.14.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.15.0 // indirect
|
||||
)
|
||||
|
||||
89
go.sum
89
go.sum
@@ -1,9 +1,9 @@
|
||||
github.com/AdguardTeam/dnsproxy v0.56.1 h1:QltfyWO7k4mxWERCEYDzkQnKzvZX/zkneWjbuJ0TU6o=
|
||||
github.com/AdguardTeam/dnsproxy v0.56.1/go.mod h1:fqmehcE3cHFNqKbWQpIjGk7GqBy7ur1v5At499lFjRc=
|
||||
github.com/AdguardTeam/golibs v0.17.1 h1:j3Ehhld5GI/amcHYG+CF0sJ4OOzAQ06BY3N/iBYJZ1M=
|
||||
github.com/AdguardTeam/golibs v0.17.1/go.mod h1:DKhCIXHcUYtBhU8ibTLKh1paUL96n5zhQBlx763sj+U=
|
||||
github.com/AdguardTeam/urlfilter v0.17.0 h1:tUzhtR9wMx704GIP3cibsDQJrixlMHfwoQbYJfPdFow=
|
||||
github.com/AdguardTeam/urlfilter v0.17.0/go.mod h1:bbuZjPUzm/Ip+nz5qPPbwIP+9rZyQbQad8Lt/0fCulU=
|
||||
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=
|
||||
github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c=
|
||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY=
|
||||
@@ -25,9 +25,9 @@ github.com/digineo/go-ipset/v2 v2.2.1 h1:k6skY+0fMqeUjjeWO/m5OuWPSZUAn7AucHMnQ1M
|
||||
github.com/digineo/go-ipset/v2 v2.2.1/go.mod h1:wBsNzJlZlABHUITkesrggFnZQtgW5wkqw1uo8Qxe0VU=
|
||||
github.com/dimfeld/httptreemux/v5 v5.5.0 h1:p8jkiMrCuZ0CmhwYLcbNbl7DDo21fozhKHQ2PccwOFQ=
|
||||
github.com/dimfeld/httptreemux/v5 v5.5.0/go.mod h1:QeEylH57C0v3VO0tkKraVz9oD3Uu93CKPnTLbsidvSw=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
github.com/go-ping/ping v1.1.0 h1:3MCGhVX4fyEUuhsfwPrsEdQw6xspHkv5zHsiSoDFZYw=
|
||||
github.com/go-ping/ping v1.1.0/go.mod h1:xIFjORFzTxqIV/tDVGO4eDy/bLuSyawEeojSm3GfRGk=
|
||||
@@ -41,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-20230926050212-f7f687d19a98 h1:pUa4ghanp6q4IJHwE9RwLgmVFfReJN+KbQ8ExNEUUoQ=
|
||||
github.com/google/pprof v0.0.0-20230926050212-f7f687d19a98/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.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/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-20230908212754-65c27093e38a h1:S33o3djA1nPRd+d/bf7jbbXytXuK/EoXow7+aa76grQ=
|
||||
github.com/insomniacslk/dhcp v0.0.0-20230908212754-65c27093e38a/go.mod h1:zmdm3sTSDP3vOOX3CEWRkkRHtKr1DxBx+J1OQFoDQQs=
|
||||
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=
|
||||
@@ -71,14 +71,14 @@ 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/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.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4=
|
||||
github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
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=
|
||||
@@ -92,10 +92,10 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
||||
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
|
||||
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4 h1:MfFAPULvst4yoMgY9QmtpYmfij/em7O8UUi+bNVm7Cg=
|
||||
github.com/quic-go/qtls-go1-20 v0.3.4/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.39.0 h1:AgP40iThFMY0bj8jGxROhw3S0FMGa8ryqsmi9tBH3So=
|
||||
github.com/quic-go/quic-go v0.39.0/go.mod h1:T09QsDQWjLiQ74ZmacDfqZmhY/NLnw5BC40MANNNZ1Q=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.40.0 h1:GYd1iznlKm7dpHD7pOVpUvItgMPo/jrMgDWZhMCecqw=
|
||||
github.com/quic-go/quic-go v0.40.0/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
|
||||
github.com/shirou/gopsutil/v3 v3.23.7 h1:C+fHO8hfIppoJ1WdsVm1RoI0RwXoNdfTK7yWXV0wVj4=
|
||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
@@ -105,39 +105,39 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/ti-mo/netfilter v0.2.0/go.mod h1:8GbBGsY/8fxtyIdfwy29JiluNcPK4K7wIT+x42ipqUU=
|
||||
github.com/ti-mo/netfilter v0.5.0 h1:MZmsUw5bFRecOb0AeyjOPxTHg4UxYzyEs0Ek/6Lxoy8=
|
||||
github.com/ti-mo/netfilter v0.5.0/go.mod h1:nt+8B9hx/QpqHr7Hazq+2qMCCA8u2OTkyc/7+U9ARz8=
|
||||
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-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.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
|
||||
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
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.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.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI=
|
||||
golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo=
|
||||
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.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY=
|
||||
golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
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.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ=
|
||||
golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
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=
|
||||
@@ -148,19 +148,18 @@ golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220622161953-175b2fd9d664/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/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.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
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.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc=
|
||||
golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg=
|
||||
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=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
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"
|
||||
@@ -141,13 +144,9 @@ func NewHostsContainer(
|
||||
func (hc *HostsContainer) Close() (err error) {
|
||||
log.Debug("%s: closing", hostsContainerPrefix)
|
||||
|
||||
err = hc.watcher.Close()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("closing fs watcher: %w", err)
|
||||
|
||||
// Go on and close the container either way.
|
||||
}
|
||||
err = errors.Annotate(hc.watcher.Close(), "closing fs watcher: %w")
|
||||
|
||||
// Go on and close the container either way.
|
||||
close(hc.done)
|
||||
|
||||
return err
|
||||
@@ -319,3 +318,39 @@ func (hc *HostsContainer) refresh() (err error) {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -10,9 +10,11 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"net/url"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
)
|
||||
@@ -307,6 +309,50 @@ func ParseAddrPort(s string, defaultPort uint16) (ipp netip.AddrPort, err error)
|
||||
return ipp, nil
|
||||
}
|
||||
|
||||
// ParseSubnet parses s either as a CIDR prefix itself, or as an IP address,
|
||||
// returning the corresponding single-IP CIDR prefix.
|
||||
//
|
||||
// TODO(e.burkov): Taken from dnsproxy, move to golibs.
|
||||
func ParseSubnet(s string) (p netip.Prefix, err error) {
|
||||
if strings.Contains(s, "/") {
|
||||
p, err = netip.ParsePrefix(s)
|
||||
if err != nil {
|
||||
return netip.Prefix{}, err
|
||||
}
|
||||
} else {
|
||||
var ip netip.Addr
|
||||
ip, err = netip.ParseAddr(s)
|
||||
if err != nil {
|
||||
return netip.Prefix{}, err
|
||||
}
|
||||
|
||||
p = netip.PrefixFrom(ip, ip.BitLen())
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
// ParseBootstraps returns the slice of upstream resolvers parsed from addrs.
|
||||
// It additionally returns the closers for each resolver, that should be closed
|
||||
// after use.
|
||||
func ParseBootstraps(
|
||||
addrs []string,
|
||||
opts *upstream.Options,
|
||||
) (boots []*upstream.UpstreamResolver, err error) {
|
||||
boots = make([]*upstream.UpstreamResolver, 0, len(boots))
|
||||
for i, b := range addrs {
|
||||
var r *upstream.UpstreamResolver
|
||||
r, err = upstream.NewUpstreamResolver(b, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bootstrap at index %d: %w", i, err)
|
||||
}
|
||||
|
||||
boots = append(boots, r)
|
||||
}
|
||||
|
||||
return boots, nil
|
||||
}
|
||||
|
||||
// BroadcastFromPref calculates the broadcast IP address for p.
|
||||
func BroadcastFromPref(p netip.Prefix) (bc netip.Addr) {
|
||||
bc = p.Addr().Unmap()
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/next/agh"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/rdns"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
"github.com/AdguardTeam/dnsproxy/proxy"
|
||||
"github.com/AdguardTeam/dnsproxy/upstream"
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
@@ -116,6 +117,26 @@ func (p *AddressUpdater) UpdateAddress(ip netip.Addr, host string, info *whois.I
|
||||
p.OnUpdateAddress(ip, host, info)
|
||||
}
|
||||
|
||||
// Package dnsforward
|
||||
|
||||
// ClientsContainer is a fake [dnsforward.ClientsContainer] implementation for
|
||||
// tests.
|
||||
type ClientsContainer struct {
|
||||
OnUpstreamConfigByID func(
|
||||
id string,
|
||||
boot upstream.Resolver,
|
||||
) (conf *proxy.CustomUpstreamConfig, err error)
|
||||
}
|
||||
|
||||
// UpstreamConfigByID implements the [dnsforward.ClientsContainer] interface
|
||||
// for *ClientsContainer.
|
||||
func (c *ClientsContainer) UpstreamConfigByID(
|
||||
id string,
|
||||
boot upstream.Resolver,
|
||||
) (conf *proxy.CustomUpstreamConfig, err error) {
|
||||
return c.OnUpstreamConfigByID(id, boot)
|
||||
}
|
||||
|
||||
// Package filtering
|
||||
|
||||
// Resolver is a fake [filtering.Resolver] implementation for tests.
|
||||
|
||||
@@ -2,6 +2,7 @@ package aghtest_test
|
||||
|
||||
import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtest"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
)
|
||||
|
||||
@@ -9,3 +10,6 @@ import (
|
||||
|
||||
// type check
|
||||
var _ filtering.Resolver = (*aghtest.Resolver)(nil)
|
||||
|
||||
// type check
|
||||
var _ dnsforward.ClientsContainer = (*aghtest.ClientsContainer)(nil)
|
||||
|
||||
@@ -7,11 +7,16 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/confmigrate"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
yaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
testutil.DiscardLogOutput(m)
|
||||
}
|
||||
|
||||
// testdata is a virtual filesystem containing test data.
|
||||
var testdata = os.DirFS("testdata")
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
)
|
||||
|
||||
@@ -49,16 +50,16 @@ type ServerConfig struct {
|
||||
// DHCPServer - DHCP server interface
|
||||
type DHCPServer interface {
|
||||
// ResetLeases resets leases.
|
||||
ResetLeases(leases []*Lease) (err error)
|
||||
ResetLeases(leases []*dhcpsvc.Lease) (err error)
|
||||
// GetLeases returns deep clones of the current leases.
|
||||
GetLeases(flags GetLeasesFlags) (leases []*Lease)
|
||||
GetLeases(flags GetLeasesFlags) (leases []*dhcpsvc.Lease)
|
||||
// AddStaticLease - add a static lease
|
||||
AddStaticLease(l *Lease) (err error)
|
||||
AddStaticLease(l *dhcpsvc.Lease) (err error)
|
||||
// RemoveStaticLease - remove a static lease
|
||||
RemoveStaticLease(l *Lease) (err error)
|
||||
RemoveStaticLease(l *dhcpsvc.Lease) (err error)
|
||||
|
||||
// UpdateStaticLease updates IP, hostname of the lease.
|
||||
UpdateStaticLease(l *Lease) (err error)
|
||||
UpdateStaticLease(l *dhcpsvc.Lease) (err error)
|
||||
|
||||
// FindMACbyIP returns a MAC address by the IP address of its lease, if
|
||||
// there is one.
|
||||
@@ -81,7 +82,7 @@ type DHCPServer interface {
|
||||
Start() (err error)
|
||||
// Stop - stop server
|
||||
Stop() (err error)
|
||||
getLeasesRef() []*Lease
|
||||
getLeasesRef() []*dhcpsvc.Lease
|
||||
}
|
||||
|
||||
// V4ServerConf - server configuration
|
||||
|
||||
@@ -5,9 +5,13 @@ package dhcpd
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/google/renameio/v2/maybe"
|
||||
@@ -28,7 +32,60 @@ type dataLeases struct {
|
||||
Version int `json:"version"`
|
||||
|
||||
// Leases is the list containing stored DHCP leases.
|
||||
Leases []*Lease `json:"leases"`
|
||||
Leases []*dbLease `json:"leases"`
|
||||
}
|
||||
|
||||
// dbLease is the structure of stored lease.
|
||||
type dbLease struct {
|
||||
Expiry string `json:"expires"`
|
||||
IP netip.Addr `json:"ip"`
|
||||
Hostname string `json:"hostname"`
|
||||
HWAddr string `json:"mac"`
|
||||
IsStatic bool `json:"static"`
|
||||
}
|
||||
|
||||
// fromLease converts *dhcpsvc.Lease to *dbLease.
|
||||
func fromLease(l *dhcpsvc.Lease) (dl *dbLease) {
|
||||
var expiryStr string
|
||||
if !l.IsStatic {
|
||||
// The front-end is waiting for RFC 3999 format of the time value. It
|
||||
// also shouldn't got an Expiry field for static leases.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2692.
|
||||
expiryStr = l.Expiry.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
return &dbLease{
|
||||
Expiry: expiryStr,
|
||||
Hostname: l.Hostname,
|
||||
HWAddr: l.HWAddr.String(),
|
||||
IP: l.IP,
|
||||
IsStatic: l.IsStatic,
|
||||
}
|
||||
}
|
||||
|
||||
// toLease converts *dbLease to *dhcpsvc.Lease.
|
||||
func (dl *dbLease) toLease() (l *dhcpsvc.Lease, err error) {
|
||||
mac, err := net.ParseMAC(dl.HWAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing hardware address: %w", err)
|
||||
}
|
||||
|
||||
expiry := time.Time{}
|
||||
if !dl.IsStatic {
|
||||
expiry, err = time.Parse(time.RFC3339, dl.Expiry)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parsing expiry time: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return &dhcpsvc.Lease{
|
||||
Expiry: expiry,
|
||||
IP: dl.IP,
|
||||
Hostname: dl.Hostname,
|
||||
HWAddr: mac,
|
||||
IsStatic: dl.IsStatic,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// dbLoad loads stored leases.
|
||||
@@ -49,15 +106,22 @@ func (s *server) dbLoad() (err error) {
|
||||
}
|
||||
|
||||
leases := dl.Leases
|
||||
|
||||
leases4 := []*Lease{}
|
||||
leases6 := []*Lease{}
|
||||
leases4 := []*dhcpsvc.Lease{}
|
||||
leases6 := []*dhcpsvc.Lease{}
|
||||
|
||||
for _, l := range leases {
|
||||
if l.IP.Is4() {
|
||||
leases4 = append(leases4, l)
|
||||
var lease *dhcpsvc.Lease
|
||||
lease, err = l.toLease()
|
||||
if err != nil {
|
||||
log.Info("dhcp: invalid lease: %s", err)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if lease.IP.Is4() {
|
||||
leases4 = append(leases4, lease)
|
||||
} else {
|
||||
leases6 = append(leases6, l)
|
||||
leases6 = append(leases6, lease)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +137,12 @@ func (s *server) dbLoad() (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("dhcp: loaded leases v4:%d v6:%d total-read:%d from DB",
|
||||
len(leases4), len(leases6), len(leases))
|
||||
log.Info(
|
||||
"dhcp: loaded leases v4:%d v6:%d total-read:%d from DB",
|
||||
len(leases4),
|
||||
len(leases6),
|
||||
len(leases),
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -83,24 +151,26 @@ func (s *server) dbLoad() (err error) {
|
||||
func (s *server) dbStore() (err error) {
|
||||
// Use an empty slice here as opposed to nil so that it doesn't write
|
||||
// "null" into the database file if leases are empty.
|
||||
leases := []*Lease{}
|
||||
leases := []*dbLease{}
|
||||
|
||||
leases4 := s.srv4.getLeasesRef()
|
||||
leases = append(leases, leases4...)
|
||||
for _, l := range s.srv4.getLeasesRef() {
|
||||
leases = append(leases, fromLease(l))
|
||||
}
|
||||
|
||||
if s.srv6 != nil {
|
||||
leases6 := s.srv6.getLeasesRef()
|
||||
leases = append(leases, leases6...)
|
||||
for _, l := range s.srv6.getLeasesRef() {
|
||||
leases = append(leases, fromLease(l))
|
||||
}
|
||||
}
|
||||
|
||||
return writeDB(s.conf.dbFilePath, leases)
|
||||
}
|
||||
|
||||
// writeDB writes leases to file at path.
|
||||
func writeDB(path string, leases []*Lease) (err error) {
|
||||
func writeDB(path string, leases []*dbLease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "writing db: %w") }()
|
||||
|
||||
slices.SortFunc(leases, func(a, b *Lease) (res int) {
|
||||
slices.SortFunc(leases, func(a, b *dbLease) (res int) {
|
||||
return strings.Compare(a.Hostname, b.Hostname)
|
||||
})
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
package dhcpd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
@@ -12,7 +11,6 @@ import (
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/timeutil"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -29,105 +27,6 @@ const (
|
||||
defaultBackoff time.Duration = 500 * time.Millisecond
|
||||
)
|
||||
|
||||
// Lease contains the necessary information about a DHCP lease. It's used as is
|
||||
// in the database, so don't change it until it's absolutely necessary, see
|
||||
// [dataVersion].
|
||||
//
|
||||
// TODO(e.burkov): Unexport it and use [dhcpsvc.Lease].
|
||||
type Lease struct {
|
||||
// Expiry is the expiration time of the lease.
|
||||
Expiry time.Time `json:"expires"`
|
||||
|
||||
// Hostname of the client.
|
||||
Hostname string `json:"hostname"`
|
||||
|
||||
// HWAddr is the physical hardware address (MAC address).
|
||||
HWAddr net.HardwareAddr `json:"mac"`
|
||||
|
||||
// IP is the IP address leased to the client.
|
||||
IP netip.Addr `json:"ip"`
|
||||
|
||||
// IsStatic defines if the lease is static.
|
||||
IsStatic bool `json:"static"`
|
||||
}
|
||||
|
||||
// Clone returns a deep copy of l.
|
||||
func (l *Lease) Clone() (clone *Lease) {
|
||||
if l == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Lease{
|
||||
Expiry: l.Expiry,
|
||||
Hostname: l.Hostname,
|
||||
HWAddr: slices.Clone(l.HWAddr),
|
||||
IP: l.IP,
|
||||
IsStatic: l.IsStatic,
|
||||
}
|
||||
}
|
||||
|
||||
// IsBlocklisted returns true if the lease is blocklisted.
|
||||
//
|
||||
// TODO(a.garipov): Just make it a boolean field.
|
||||
func (l *Lease) IsBlocklisted() (ok bool) {
|
||||
if len(l.HWAddr) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, b := range l.HWAddr {
|
||||
if b != 0 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// MarshalJSON implements the json.Marshaler interface for Lease.
|
||||
func (l Lease) MarshalJSON() ([]byte, error) {
|
||||
var expiryStr string
|
||||
if !l.IsStatic {
|
||||
// The front-end is waiting for RFC 3999 format of the time
|
||||
// value. It also shouldn't got an Expiry field for static
|
||||
// leases.
|
||||
//
|
||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/2692.
|
||||
expiryStr = l.Expiry.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
type lease Lease
|
||||
return json.Marshal(&struct {
|
||||
HWAddr string `json:"mac"`
|
||||
Expiry string `json:"expires,omitempty"`
|
||||
lease
|
||||
}{
|
||||
HWAddr: l.HWAddr.String(),
|
||||
Expiry: expiryStr,
|
||||
lease: lease(l),
|
||||
})
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements the json.Unmarshaler interface for *Lease.
|
||||
func (l *Lease) UnmarshalJSON(data []byte) (err error) {
|
||||
type lease Lease
|
||||
aux := struct {
|
||||
*lease
|
||||
HWAddr string `json:"mac"`
|
||||
}{
|
||||
lease: (*lease)(l),
|
||||
}
|
||||
if err = json.Unmarshal(data, &aux); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
l.HWAddr, err = net.ParseMAC(aux.HWAddr)
|
||||
if err != nil {
|
||||
return fmt.Errorf("couldn't parse MAC address: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// OnLeaseChangedT is a callback for lease changes.
|
||||
type OnLeaseChangedT func(flags int)
|
||||
|
||||
@@ -370,19 +269,7 @@ func (s *server) Stop() (err error) {
|
||||
|
||||
// Leases returns the list of active DHCP leases.
|
||||
func (s *server) Leases() (leases []*dhcpsvc.Lease) {
|
||||
ls := append(s.srv4.GetLeases(LeasesAll), s.srv6.GetLeases(LeasesAll)...)
|
||||
leases = make([]*dhcpsvc.Lease, len(ls))
|
||||
for i, l := range ls {
|
||||
leases[i] = &dhcpsvc.Lease{
|
||||
Expiry: l.Expiry,
|
||||
Hostname: l.Hostname,
|
||||
HWAddr: l.HWAddr,
|
||||
IP: l.IP,
|
||||
IsStatic: l.IsStatic,
|
||||
}
|
||||
}
|
||||
|
||||
return leases
|
||||
return append(s.srv4.GetLeases(LeasesAll), s.srv6.GetLeases(LeasesAll)...)
|
||||
}
|
||||
|
||||
// MACByIP returns a MAC address by the IP address of its lease, if there is
|
||||
@@ -414,6 +301,6 @@ func (s *server) IPByHost(host string) (ip netip.Addr) {
|
||||
}
|
||||
|
||||
// AddStaticLease - add static v4 lease
|
||||
func (s *server) AddStaticLease(l *Lease) error {
|
||||
func (s *server) AddStaticLease(l *dhcpsvc.Lease) error {
|
||||
return s.srv4.AddStaticLease(l)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -44,7 +45,7 @@ func TestDB(t *testing.T) {
|
||||
s.srv6, err = v6Create(V6ServerConf{})
|
||||
require.NoError(t, err)
|
||||
|
||||
leases := []*Lease{{
|
||||
leases := []*dhcpsvc.Lease{{
|
||||
Expiry: time.Now().Add(time.Hour),
|
||||
Hostname: "static-1.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
|
||||
@@ -93,13 +93,13 @@ func leasesToStatic(leases []*dhcpsvc.Lease) (static []*leaseStatic) {
|
||||
}
|
||||
|
||||
// toLease converts leaseStatic to Lease or returns error.
|
||||
func (l *leaseStatic) toLease() (lease *Lease, err error) {
|
||||
func (l *leaseStatic) toLease() (lease *dhcpsvc.Lease, err error) {
|
||||
addr, err := net.ParseMAC(l.HWAddr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't parse MAC address: %w", err)
|
||||
}
|
||||
|
||||
return &Lease{
|
||||
return &dhcpsvc.Lease{
|
||||
HWAddr: addr,
|
||||
IP: l.IP,
|
||||
Hostname: l.Hostname,
|
||||
@@ -593,7 +593,7 @@ func setOtherDHCPResult(ifaceName string, result *dhcpSearchResult) {
|
||||
|
||||
// parseLease parses a lease from r. If there is no error returns DHCPServer
|
||||
// and *Lease. r must be non-nil.
|
||||
func (s *server) parseLease(r io.Reader) (srv DHCPServer, lease *Lease, err error) {
|
||||
func (s *server) parseLease(r io.Reader) (srv DHCPServer, lease *dhcpsvc.Lease, err error) {
|
||||
l := &leaseStatic{}
|
||||
err = json.NewDecoder(r).Decode(l)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,6 +2,7 @@ package dhcpd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
@@ -25,9 +26,9 @@ const (
|
||||
dbFilename = "leases.db"
|
||||
)
|
||||
|
||||
// leaseJSON is the structure of stored lease.
|
||||
// leaseJSON is the structure of stored lease in a legacy database.
|
||||
//
|
||||
// Deprecated: Use [Lease].
|
||||
// Deprecated: Use [dbLease].
|
||||
type leaseJSON struct {
|
||||
HWAddr []byte `json:"mac"`
|
||||
IP []byte `json:"ip"`
|
||||
@@ -35,13 +36,28 @@ type leaseJSON struct {
|
||||
Expiry int64 `json:"exp"`
|
||||
}
|
||||
|
||||
func normalizeIP(ip net.IP) net.IP {
|
||||
ip4 := ip.To4()
|
||||
if ip4 != nil {
|
||||
return ip4
|
||||
// readOldDB reads the old database from the given path.
|
||||
func readOldDB(path string) (leases []*leaseJSON, err error) {
|
||||
// #nosec G304 -- Trust this path, since it's taken from the old file name
|
||||
// relative to the working directory and should generally be considered
|
||||
// safe.
|
||||
file, err := os.Open(path)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
// Nothing to migrate.
|
||||
return nil, nil
|
||||
} else if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return nil, err
|
||||
}
|
||||
defer func() { err = errors.WithDeferred(err, file.Close()) }()
|
||||
|
||||
leases = []*leaseJSON{}
|
||||
err = json.NewDecoder(file).Decode(&leases)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decoding old db: %w", err)
|
||||
}
|
||||
|
||||
return ip
|
||||
return leases, nil
|
||||
}
|
||||
|
||||
// migrateDB migrates stored leases if necessary.
|
||||
@@ -51,59 +67,50 @@ func migrateDB(conf *ServerConfig) (err error) {
|
||||
oldLeasesPath := filepath.Join(conf.WorkDir, dbFilename)
|
||||
dataDirPath := filepath.Join(conf.DataDir, dataFilename)
|
||||
|
||||
// #nosec G304 -- Trust this path, since it's taken from the old file name
|
||||
// relative to the working directory and should generally be considered
|
||||
// safe.
|
||||
file, err := os.Open(oldLeasesPath)
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
oldLeases, err := readOldDB(oldLeasesPath)
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
} else if oldLeases == nil {
|
||||
// Nothing to migrate.
|
||||
return nil
|
||||
} else if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
ljs := []leaseJSON{}
|
||||
err = json.NewDecoder(file).Decode(&ljs)
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
|
||||
leases := []*Lease{}
|
||||
|
||||
for _, lj := range ljs {
|
||||
lj.IP = normalizeIP(lj.IP)
|
||||
|
||||
ip, ok := netip.AddrFromSlice(lj.IP)
|
||||
leases := make([]*dbLease, 0, len(oldLeases))
|
||||
for _, l := range oldLeases {
|
||||
l.IP = normalizeIP(l.IP)
|
||||
ip, ok := netip.AddrFromSlice(l.IP)
|
||||
if !ok {
|
||||
log.Info("dhcp: invalid IP: %s", lj.IP)
|
||||
log.Info("dhcp: invalid IP: %s", l.IP)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
lease := &Lease{
|
||||
Expiry: time.Unix(lj.Expiry, 0),
|
||||
Hostname: lj.Hostname,
|
||||
HWAddr: lj.HWAddr,
|
||||
leases = append(leases, &dbLease{
|
||||
Expiry: time.Unix(l.Expiry, 0).Format(time.RFC3339),
|
||||
Hostname: l.Hostname,
|
||||
HWAddr: net.HardwareAddr(l.HWAddr).String(),
|
||||
IP: ip,
|
||||
IsStatic: lj.Expiry == leaseExpireStatic,
|
||||
}
|
||||
|
||||
leases = append(leases, lease)
|
||||
IsStatic: l.Expiry == leaseExpireStatic,
|
||||
})
|
||||
}
|
||||
|
||||
err = writeDB(dataDirPath, leases)
|
||||
if err != nil {
|
||||
// Don't wrap the error since it's informative enough as is.
|
||||
// Don't wrap the error since an annotation deferred already.
|
||||
return err
|
||||
}
|
||||
|
||||
return os.Remove(oldLeasesPath)
|
||||
}
|
||||
|
||||
// normalizeIP converts the given IP address to IPv4 if it's IPv4-mapped IPv6,
|
||||
// or leaves it as is otherwise.
|
||||
func normalizeIP(ip net.IP) (normalized net.IP) {
|
||||
normalized = ip.To4()
|
||||
if normalized != nil {
|
||||
return normalized
|
||||
}
|
||||
|
||||
return ip
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@ package dhcpd
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"path/filepath"
|
||||
@@ -27,16 +26,16 @@ func TestMigrateDB(t *testing.T) {
|
||||
err := os.WriteFile(oldLeasesPath, []byte(testData), 0o644)
|
||||
require.NoError(t, err)
|
||||
|
||||
wantLeases := []*Lease{{
|
||||
Expiry: time.Time{},
|
||||
wantLeases := []*dbLease{{
|
||||
Expiry: time.Unix(1, 0).Format(time.RFC3339),
|
||||
Hostname: "test1",
|
||||
HWAddr: net.HardwareAddr{0x11, 0x22, 0x33, 0x44, 0x55, 0x66},
|
||||
HWAddr: "11:22:33:44:55:66",
|
||||
IP: netip.MustParseAddr("1.2.3.4"),
|
||||
IsStatic: true,
|
||||
}, {
|
||||
Expiry: time.Unix(1231231231, 0),
|
||||
Expiry: time.Unix(1231231231, 0).Format(time.RFC3339),
|
||||
Hostname: "test2",
|
||||
HWAddr: net.HardwareAddr{0x66, 0x55, 0x44, 0x33, 0x22, 0x11},
|
||||
HWAddr: "66:55:44:33:22:11",
|
||||
IP: netip.MustParseAddr("4.3.2.1"),
|
||||
IsStatic: false,
|
||||
}}
|
||||
@@ -62,12 +61,12 @@ func TestMigrateDB(t *testing.T) {
|
||||
|
||||
leases := dl.Leases
|
||||
|
||||
for i, wl := range wantLeases {
|
||||
assert.Equal(t, wl.Hostname, leases[i].Hostname)
|
||||
assert.Equal(t, wl.HWAddr, leases[i].HWAddr)
|
||||
assert.Equal(t, wl.IP, leases[i].IP)
|
||||
assert.Equal(t, wl.IsStatic, leases[i].IsStatic)
|
||||
for i, wantLease := range wantLeases {
|
||||
assert.Equal(t, wantLease.Hostname, leases[i].Hostname)
|
||||
assert.Equal(t, wantLease.HWAddr, leases[i].HWAddr)
|
||||
assert.Equal(t, wantLease.IP, leases[i].IP)
|
||||
assert.Equal(t, wantLease.IsStatic, leases[i].IsStatic)
|
||||
|
||||
require.True(t, wl.Expiry.Equal(leases[i].Expiry))
|
||||
require.Equal(t, wantLease.Expiry, leases[i].Expiry)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@ package dhcpd
|
||||
import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
)
|
||||
|
||||
type winServer struct{}
|
||||
@@ -14,19 +16,19 @@ type winServer struct{}
|
||||
// type check
|
||||
var _ DHCPServer = winServer{}
|
||||
|
||||
func (winServer) ResetLeases(_ []*Lease) (err error) { return nil }
|
||||
func (winServer) GetLeases(_ GetLeasesFlags) (leases []*Lease) { return nil }
|
||||
func (winServer) getLeasesRef() []*Lease { return nil }
|
||||
func (winServer) AddStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) RemoveStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) UpdateStaticLease(_ *Lease) (err error) { return nil }
|
||||
func (winServer) FindMACbyIP(_ netip.Addr) (mac net.HardwareAddr) { return nil }
|
||||
func (winServer) WriteDiskConfig4(_ *V4ServerConf) {}
|
||||
func (winServer) WriteDiskConfig6(_ *V6ServerConf) {}
|
||||
func (winServer) Start() (err error) { return nil }
|
||||
func (winServer) Stop() (err error) { return nil }
|
||||
func (winServer) HostByIP(_ netip.Addr) (host string) { return "" }
|
||||
func (winServer) IPByHost(_ string) (ip netip.Addr) { return netip.Addr{} }
|
||||
func (winServer) ResetLeases(_ []*dhcpsvc.Lease) (err error) { return nil }
|
||||
func (winServer) GetLeases(_ GetLeasesFlags) (leases []*dhcpsvc.Lease) { return nil }
|
||||
func (winServer) getLeasesRef() []*dhcpsvc.Lease { return nil }
|
||||
func (winServer) AddStaticLease(_ *dhcpsvc.Lease) (err error) { return nil }
|
||||
func (winServer) RemoveStaticLease(_ *dhcpsvc.Lease) (err error) { return nil }
|
||||
func (winServer) UpdateStaticLease(_ *dhcpsvc.Lease) (err error) { return nil }
|
||||
func (winServer) FindMACbyIP(_ netip.Addr) (mac net.HardwareAddr) { return nil }
|
||||
func (winServer) WriteDiskConfig4(_ *V4ServerConf) {}
|
||||
func (winServer) WriteDiskConfig6(_ *V6ServerConf) {}
|
||||
func (winServer) Start() (err error) { return nil }
|
||||
func (winServer) Stop() (err error) { return nil }
|
||||
func (winServer) HostByIP(_ netip.Addr) (host string) { return "" }
|
||||
func (winServer) IPByHost(_ string) (ip netip.Addr) { return netip.Addr{} }
|
||||
|
||||
func v4Create(_ *V4ServerConf) (s DHCPServer, err error) { return winServer{}, nil }
|
||||
func v6Create(_ V6ServerConf) (s DHCPServer, err error) { return winServer{}, nil }
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
@@ -38,7 +39,7 @@ type v4Server struct {
|
||||
// have intersections with [implicitOpts].
|
||||
explicitOpts dhcpv4.Options
|
||||
|
||||
// leasesLock protects leases, leaseHosts, and leasedOffsets.
|
||||
// leasesLock protects leases, hostsIndex, ipIndex, and leasedOffsets.
|
||||
leasesLock sync.Mutex
|
||||
|
||||
// leasedOffsets contains offsets from conf.ipRange.start that have been
|
||||
@@ -46,13 +47,13 @@ type v4Server struct {
|
||||
leasedOffsets *bitSet
|
||||
|
||||
// leases contains all dynamic and static leases.
|
||||
leases []*Lease
|
||||
leases []*dhcpsvc.Lease
|
||||
|
||||
// hostsIndex is the set of all hostnames of all known DHCP clients.
|
||||
hostsIndex map[string]*Lease
|
||||
hostsIndex map[string]*dhcpsvc.Lease
|
||||
|
||||
// ipIndex is an index of leases by their IP addresses.
|
||||
ipIndex map[netip.Addr]*Lease
|
||||
ipIndex map[netip.Addr]*dhcpsvc.Lease
|
||||
}
|
||||
|
||||
func (s *v4Server) enabled() (ok bool) {
|
||||
@@ -141,7 +142,7 @@ func (s *v4Server) IPByHost(host string) (ip netip.Addr) {
|
||||
}
|
||||
|
||||
// ResetLeases resets leases.
|
||||
func (s *v4Server) ResetLeases(leases []*Lease) (err error) {
|
||||
func (s *v4Server) ResetLeases(leases []*dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv4: %w") }()
|
||||
|
||||
if s.conf == nil {
|
||||
@@ -152,8 +153,8 @@ func (s *v4Server) ResetLeases(leases []*Lease) (err error) {
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
s.leasedOffsets = newBitSet()
|
||||
s.hostsIndex = make(map[string]*Lease, len(leases))
|
||||
s.ipIndex = make(map[netip.Addr]*Lease, len(leases))
|
||||
s.hostsIndex = make(map[string]*dhcpsvc.Lease, len(leases))
|
||||
s.ipIndex = make(map[netip.Addr]*dhcpsvc.Lease, len(leases))
|
||||
s.leases = nil
|
||||
|
||||
for _, l := range leases {
|
||||
@@ -173,14 +174,14 @@ func (s *v4Server) ResetLeases(leases []*Lease) (err error) {
|
||||
}
|
||||
|
||||
// getLeasesRef returns the actual leases slice. For internal use only.
|
||||
func (s *v4Server) getLeasesRef() []*Lease {
|
||||
func (s *v4Server) getLeasesRef() []*dhcpsvc.Lease {
|
||||
return s.leases
|
||||
}
|
||||
|
||||
// isBlocklisted returns true if this lease holds a blocklisted IP.
|
||||
//
|
||||
// TODO(a.garipov): Make a method of *Lease?
|
||||
func (s *v4Server) isBlocklisted(l *Lease) (ok bool) {
|
||||
func (s *v4Server) isBlocklisted(l *dhcpsvc.Lease) (ok bool) {
|
||||
if len(l.HWAddr) == 0 {
|
||||
return false
|
||||
}
|
||||
@@ -196,11 +197,11 @@ func (s *v4Server) isBlocklisted(l *Lease) (ok bool) {
|
||||
|
||||
// GetLeases returns the list of current DHCP leases. It is safe for concurrent
|
||||
// use.
|
||||
func (s *v4Server) GetLeases(flags GetLeasesFlags) (leases []*Lease) {
|
||||
func (s *v4Server) GetLeases(flags GetLeasesFlags) (leases []*dhcpsvc.Lease) {
|
||||
// The function shouldn't return nil, because zero-length slice behaves
|
||||
// differently in cases like marshalling. Our front-end also requires
|
||||
// a non-nil value in the response.
|
||||
leases = []*Lease{}
|
||||
leases = []*dhcpsvc.Lease{}
|
||||
|
||||
getDynamic := flags&LeasesDynamic != 0
|
||||
getStatic := flags&LeasesStatic != 0
|
||||
@@ -248,7 +249,7 @@ func (s *v4Server) FindMACbyIP(ip netip.Addr) (mac net.HardwareAddr) {
|
||||
const defaultHwAddrLen = 6
|
||||
|
||||
// Add the specified IP to the black list for a time period
|
||||
func (s *v4Server) blocklistLease(l *Lease) {
|
||||
func (s *v4Server) blocklistLease(l *dhcpsvc.Lease) {
|
||||
l.HWAddr = make(net.HardwareAddr, defaultHwAddrLen)
|
||||
l.Hostname = ""
|
||||
l.Expiry = time.Now().Add(s.conf.leaseTime)
|
||||
@@ -284,7 +285,7 @@ func (s *v4Server) rmLeaseByIndex(i int) {
|
||||
// Return error if a static lease is found
|
||||
//
|
||||
// TODO(s.chzhen): Refactor the code.
|
||||
func (s *v4Server) rmDynamicLease(lease *Lease) (err error) {
|
||||
func (s *v4Server) rmDynamicLease(lease *dhcpsvc.Lease) (err error) {
|
||||
for i, l := range s.leases {
|
||||
isStatic := l.IsStatic
|
||||
|
||||
@@ -320,7 +321,7 @@ const (
|
||||
)
|
||||
|
||||
// addLease adds a dynamic or static lease.
|
||||
func (s *v4Server) addLease(l *Lease) (err error) {
|
||||
func (s *v4Server) addLease(l *dhcpsvc.Lease) (err error) {
|
||||
r := s.conf.ipRange
|
||||
leaseIP := net.IP(l.IP.AsSlice())
|
||||
offset, inOffset := r.offset(leaseIP)
|
||||
@@ -352,7 +353,7 @@ func (s *v4Server) addLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// rmLease removes a lease with the same properties.
|
||||
func (s *v4Server) rmLease(lease *Lease) (err error) {
|
||||
func (s *v4Server) rmLease(lease *dhcpsvc.Lease) (err error) {
|
||||
if len(s.leases) == 0 {
|
||||
return nil
|
||||
}
|
||||
@@ -378,7 +379,7 @@ const ErrUnconfigured errors.Error = "server is unconfigured"
|
||||
|
||||
// AddStaticLease implements the DHCPServer interface for *v4Server. It is
|
||||
// safe for concurrent use.
|
||||
func (s *v4Server) AddStaticLease(l *Lease) (err error) {
|
||||
func (s *v4Server) AddStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv4: adding static lease: %w") }()
|
||||
|
||||
if s.conf == nil {
|
||||
@@ -435,7 +436,7 @@ func (s *v4Server) AddStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// UpdateStaticLease updates IP, hostname of the static lease.
|
||||
func (s *v4Server) UpdateStaticLease(l *Lease) (err error) {
|
||||
func (s *v4Server) UpdateStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = errors.Annotate(err, "dhcpv4: updating static lease: %w")
|
||||
@@ -474,7 +475,7 @@ func (s *v4Server) UpdateStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// validateStaticLease returns an error if the static lease is invalid.
|
||||
func (s *v4Server) validateStaticLease(l *Lease) (err error) {
|
||||
func (s *v4Server) validateStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
hostname, err := normalizeHostname(l.Hostname)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
@@ -511,7 +512,7 @@ func (s *v4Server) validateStaticLease(l *Lease) (err error) {
|
||||
|
||||
// updateStaticLease safe removes dynamic lease with the same properties and
|
||||
// then adds a static lease l.
|
||||
func (s *v4Server) updateStaticLease(l *Lease) (err error) {
|
||||
func (s *v4Server) updateStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
@@ -529,7 +530,7 @@ func (s *v4Server) updateStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// RemoveStaticLease removes a static lease. It is safe for concurrent use.
|
||||
func (s *v4Server) RemoveStaticLease(l *Lease) (err error) {
|
||||
func (s *v4Server) RemoveStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv4: %w") }()
|
||||
|
||||
if s.conf == nil {
|
||||
@@ -606,7 +607,7 @@ func (s *v4Server) addrAvailable(target net.IP) (avail bool) {
|
||||
}
|
||||
|
||||
// findLease finds a lease by its MAC-address.
|
||||
func (s *v4Server) findLease(mac net.HardwareAddr) (l *Lease) {
|
||||
func (s *v4Server) findLease(mac net.HardwareAddr) (l *dhcpsvc.Lease) {
|
||||
for _, l = range s.leases {
|
||||
if bytes.Equal(mac, l.HWAddr) {
|
||||
return l
|
||||
@@ -646,8 +647,8 @@ func (s *v4Server) findExpiredLease() int {
|
||||
|
||||
// reserveLease reserves a lease for a client by its MAC-address. It returns
|
||||
// nil if it couldn't allocate a new lease.
|
||||
func (s *v4Server) reserveLease(mac net.HardwareAddr) (l *Lease, err error) {
|
||||
l = &Lease{HWAddr: slices.Clone(mac)}
|
||||
func (s *v4Server) reserveLease(mac net.HardwareAddr) (l *dhcpsvc.Lease, err error) {
|
||||
l = &dhcpsvc.Lease{HWAddr: slices.Clone(mac)}
|
||||
|
||||
nextIP := s.nextIP()
|
||||
if nextIP == nil {
|
||||
@@ -679,7 +680,7 @@ func (s *v4Server) reserveLease(mac net.HardwareAddr) (l *Lease, err error) {
|
||||
// commitLease refreshes l's values. It takes the desired hostname into account
|
||||
// when setting it into the lease, but generates a unique one if the provided
|
||||
// can't be used.
|
||||
func (s *v4Server) commitLease(l *Lease, hostname string) {
|
||||
func (s *v4Server) commitLease(l *dhcpsvc.Lease, hostname string) {
|
||||
prev := l.Hostname
|
||||
hostname = s.validHostnameForClient(hostname, l.IP)
|
||||
|
||||
@@ -709,7 +710,7 @@ func (s *v4Server) commitLease(l *Lease, hostname string) {
|
||||
|
||||
// allocateLease allocates a new lease for the MAC address. If there are no IP
|
||||
// addresses left, both l and err are nil.
|
||||
func (s *v4Server) allocateLease(mac net.HardwareAddr) (l *Lease, err error) {
|
||||
func (s *v4Server) allocateLease(mac net.HardwareAddr) (l *dhcpsvc.Lease, err error) {
|
||||
for {
|
||||
l, err = s.reserveLease(mac)
|
||||
if err != nil {
|
||||
@@ -728,7 +729,7 @@ func (s *v4Server) allocateLease(mac net.HardwareAddr) (l *Lease, err error) {
|
||||
}
|
||||
|
||||
// handleDiscover is the handler for the DHCP Discover request.
|
||||
func (s *v4Server) handleDiscover(req, resp *dhcpv4.DHCPv4) (l *Lease, err error) {
|
||||
func (s *v4Server) handleDiscover(req, resp *dhcpv4.DHCPv4) (l *dhcpsvc.Lease, err error) {
|
||||
mac := req.ClientHWAddr
|
||||
|
||||
defer s.conf.notify(LeaseChangedDBStore)
|
||||
@@ -787,7 +788,7 @@ func OptionFQDN(fqdn string) (opt dhcpv4.Option) {
|
||||
// checkLease checks if the pair of mac and ip is already leased. The mismatch
|
||||
// is true when the existing lease has the same hardware address but differs in
|
||||
// its IP address.
|
||||
func (s *v4Server) checkLease(mac net.HardwareAddr, ip net.IP) (lease *Lease, mismatch bool) {
|
||||
func (s *v4Server) checkLease(mac net.HardwareAddr, ip net.IP) (l *dhcpsvc.Lease, mismatch bool) {
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
@@ -798,7 +799,7 @@ func (s *v4Server) checkLease(mac net.HardwareAddr, ip net.IP) (lease *Lease, mi
|
||||
return nil, false
|
||||
}
|
||||
|
||||
for _, l := range s.leases {
|
||||
for _, l = range s.leases {
|
||||
if !bytes.Equal(l.HWAddr, mac) {
|
||||
continue
|
||||
}
|
||||
@@ -823,7 +824,7 @@ func (s *v4Server) handleSelecting(
|
||||
req *dhcpv4.DHCPv4,
|
||||
reqIP net.IP,
|
||||
sid net.IP,
|
||||
) (l *Lease, needsReply bool) {
|
||||
) (l *dhcpsvc.Lease, needsReply bool) {
|
||||
// Client inserts the address of the selected server in server identifier,
|
||||
// ciaddr MUST be zero.
|
||||
mac := req.ClientHWAddr
|
||||
@@ -857,7 +858,10 @@ func (s *v4Server) handleSelecting(
|
||||
}
|
||||
|
||||
// handleInitReboot handles the DHCPREQUEST generated during INIT-REBOOT state.
|
||||
func (s *v4Server) handleInitReboot(req *dhcpv4.DHCPv4, reqIP net.IP) (l *Lease, needsReply bool) {
|
||||
func (s *v4Server) handleInitReboot(
|
||||
req *dhcpv4.DHCPv4,
|
||||
reqIP net.IP,
|
||||
) (l *dhcpsvc.Lease, needsReply bool) {
|
||||
mac := req.ClientHWAddr
|
||||
|
||||
ip4 := reqIP.To4()
|
||||
@@ -899,7 +903,7 @@ func (s *v4Server) handleInitReboot(req *dhcpv4.DHCPv4, reqIP net.IP) (l *Lease,
|
||||
|
||||
// handleRenew handles the DHCPREQUEST generated during RENEWING or REBINDING
|
||||
// state.
|
||||
func (s *v4Server) handleRenew(req *dhcpv4.DHCPv4) (l *Lease, needsReply bool) {
|
||||
func (s *v4Server) handleRenew(req *dhcpv4.DHCPv4) (l *dhcpsvc.Lease, needsReply bool) {
|
||||
mac := req.ClientHWAddr
|
||||
|
||||
// ciaddr MUST be filled in with client's IP address.
|
||||
@@ -926,7 +930,7 @@ func (s *v4Server) handleRenew(req *dhcpv4.DHCPv4) (l *Lease, needsReply bool) {
|
||||
|
||||
// handleByRequestType handles the DHCPREQUEST according to the state during
|
||||
// which it's generated by client.
|
||||
func (s *v4Server) handleByRequestType(req *dhcpv4.DHCPv4) (lease *Lease, needsReply bool) {
|
||||
func (s *v4Server) handleByRequestType(req *dhcpv4.DHCPv4) (lease *dhcpsvc.Lease, needsReply bool) {
|
||||
reqIP, sid := req.RequestedIPAddress(), req.ServerIdentifier()
|
||||
|
||||
if sid != nil && !sid.IsUnspecified() {
|
||||
@@ -950,7 +954,7 @@ func (s *v4Server) handleByRequestType(req *dhcpv4.DHCPv4) (lease *Lease, needsR
|
||||
// handleRequest is the handler for a DHCPREQUEST message.
|
||||
//
|
||||
// See https://datatracker.ietf.org/doc/html/rfc2131#section-4.3.2.
|
||||
func (s *v4Server) handleRequest(req, resp *dhcpv4.DHCPv4) (lease *Lease, needsReply bool) {
|
||||
func (s *v4Server) handleRequest(req, resp *dhcpv4.DHCPv4) (lease *dhcpsvc.Lease, needsReply bool) {
|
||||
lease, needsReply = s.handleByRequestType(req)
|
||||
if lease == nil {
|
||||
return nil, needsReply
|
||||
@@ -1043,7 +1047,7 @@ func (s *v4Server) handleDecline(req, resp *dhcpv4.DHCPv4) (err error) {
|
||||
}
|
||||
|
||||
// findLeaseForIP returns a lease for provided ip and mac.
|
||||
func (s *v4Server) findLeaseForIP(ip net.IP, mac net.HardwareAddr) (l *Lease) {
|
||||
func (s *v4Server) findLeaseForIP(ip net.IP, mac net.HardwareAddr) (l *dhcpsvc.Lease) {
|
||||
netIP, ok := netip.AddrFromSlice(ip)
|
||||
if !ok {
|
||||
log.Info("dhcpv4: invalid IP: %s", ip)
|
||||
@@ -1106,7 +1110,11 @@ func (s *v4Server) handleRelease(req, resp *dhcpv4.DHCPv4) (err error) {
|
||||
}
|
||||
|
||||
// messageHandler describes a DHCPv4 message handler function.
|
||||
type messageHandler func(s *v4Server, req, resp *dhcpv4.DHCPv4) (rCode int, l *Lease, err error)
|
||||
type messageHandler func(
|
||||
s *v4Server,
|
||||
req *dhcpv4.DHCPv4,
|
||||
resp *dhcpv4.DHCPv4,
|
||||
) (rCode int, l *dhcpsvc.Lease, err error)
|
||||
|
||||
// messageHandlers is a map of handlers for various messages with message types
|
||||
// keys.
|
||||
@@ -1115,7 +1123,7 @@ var messageHandlers = map[dhcpv4.MessageType]messageHandler{
|
||||
s *v4Server,
|
||||
req *dhcpv4.DHCPv4,
|
||||
resp *dhcpv4.DHCPv4,
|
||||
) (rCode int, l *Lease, err error) {
|
||||
) (rCode int, l *dhcpsvc.Lease, err error) {
|
||||
l, err = s.handleDiscover(req, resp)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("handling discover: %s", err)
|
||||
@@ -1131,7 +1139,7 @@ var messageHandlers = map[dhcpv4.MessageType]messageHandler{
|
||||
s *v4Server,
|
||||
req *dhcpv4.DHCPv4,
|
||||
resp *dhcpv4.DHCPv4,
|
||||
) (rCode int, l *Lease, err error) {
|
||||
) (rCode int, l *dhcpsvc.Lease, err error) {
|
||||
var toReply bool
|
||||
l, toReply = s.handleRequest(req, resp)
|
||||
if l == nil {
|
||||
@@ -1149,7 +1157,7 @@ var messageHandlers = map[dhcpv4.MessageType]messageHandler{
|
||||
s *v4Server,
|
||||
req *dhcpv4.DHCPv4,
|
||||
resp *dhcpv4.DHCPv4,
|
||||
) (rCode int, l *Lease, err error) {
|
||||
) (rCode int, l *dhcpsvc.Lease, err error) {
|
||||
err = s.handleDecline(req, resp)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("handling decline: %s", err)
|
||||
@@ -1161,7 +1169,7 @@ var messageHandlers = map[dhcpv4.MessageType]messageHandler{
|
||||
s *v4Server,
|
||||
req *dhcpv4.DHCPv4,
|
||||
resp *dhcpv4.DHCPv4,
|
||||
) (rCode int, l *Lease, err error) {
|
||||
) (rCode int, l *dhcpsvc.Lease, err error) {
|
||||
err = s.handleRelease(req, resp)
|
||||
if err != nil {
|
||||
return 0, nil, fmt.Errorf("handling release: %s", err)
|
||||
@@ -1402,8 +1410,8 @@ func (s *v4Server) Stop() (err error) {
|
||||
// Create DHCPv4 server
|
||||
func v4Create(conf *V4ServerConf) (srv *v4Server, err error) {
|
||||
s := &v4Server{
|
||||
hostsIndex: map[string]*Lease{},
|
||||
ipIndex: map[netip.Addr]*Lease{},
|
||||
hostsIndex: map[string]*dhcpsvc.Lease{},
|
||||
ipIndex: map[netip.Addr]*dhcpsvc.Lease{},
|
||||
}
|
||||
|
||||
err = conf.Validate()
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
"github.com/AdguardTeam/golibs/stringutil"
|
||||
"github.com/AdguardTeam/golibs/testutil"
|
||||
@@ -67,7 +68,7 @@ func TestV4Server_leasing(t *testing.T) {
|
||||
s := defaultSrv(t)
|
||||
|
||||
t.Run("add_static", func(t *testing.T) {
|
||||
err := s.AddStaticLease(&Lease{
|
||||
err := s.AddStaticLease(&dhcpsvc.Lease{
|
||||
Hostname: staticName,
|
||||
HWAddr: staticMAC,
|
||||
IP: staticIP,
|
||||
@@ -76,7 +77,7 @@ func TestV4Server_leasing(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("same_name", func(t *testing.T) {
|
||||
err = s.AddStaticLease(&Lease{
|
||||
err = s.AddStaticLease(&dhcpsvc.Lease{
|
||||
Hostname: staticName,
|
||||
HWAddr: anotherMAC,
|
||||
IP: anotherIP,
|
||||
@@ -90,7 +91,7 @@ func TestV4Server_leasing(t *testing.T) {
|
||||
"dynamic leases for " + anotherIP.String() +
|
||||
" (" + staticMAC.String() + "): static lease already exists"
|
||||
|
||||
err = s.AddStaticLease(&Lease{
|
||||
err = s.AddStaticLease(&dhcpsvc.Lease{
|
||||
Hostname: anotherName,
|
||||
HWAddr: staticMAC,
|
||||
IP: anotherIP,
|
||||
@@ -104,7 +105,7 @@ func TestV4Server_leasing(t *testing.T) {
|
||||
"dynamic leases for " + staticIP.String() +
|
||||
" (" + anotherMAC.String() + "): static lease already exists"
|
||||
|
||||
err = s.AddStaticLease(&Lease{
|
||||
err = s.AddStaticLease(&dhcpsvc.Lease{
|
||||
Hostname: anotherName,
|
||||
HWAddr: anotherMAC,
|
||||
IP: staticIP,
|
||||
@@ -208,11 +209,11 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
require.Empty(t, ls)
|
||||
|
||||
testCases := []struct {
|
||||
lease *Lease
|
||||
lease *dhcpsvc.Lease
|
||||
name string
|
||||
wantErrMsg string
|
||||
}{{
|
||||
lease: &Lease{
|
||||
lease: &dhcpsvc.Lease{
|
||||
Hostname: "success.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -220,7 +221,7 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
name: "success",
|
||||
wantErrMsg: "",
|
||||
}, {
|
||||
lease: &Lease{
|
||||
lease: &dhcpsvc.Lease{
|
||||
Hostname: "probably-router.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: DefaultGatewayIP,
|
||||
@@ -229,7 +230,7 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
wantErrMsg: "dhcpv4: adding static lease: " +
|
||||
`can't assign the gateway IP "192.168.10.1" to the lease`,
|
||||
}, {
|
||||
lease: &Lease{
|
||||
lease: &dhcpsvc.Lease{
|
||||
Hostname: "ip6.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("ffff::1"),
|
||||
@@ -238,7 +239,7 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
wantErrMsg: `dhcpv4: adding static lease: ` +
|
||||
`invalid IP "ffff::1": only IPv4 is supported`,
|
||||
}, {
|
||||
lease: &Lease{
|
||||
lease: &dhcpsvc.Lease{
|
||||
Hostname: "bad-mac.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -247,7 +248,7 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
wantErrMsg: `dhcpv4: adding static lease: bad mac address "aa:aa": ` +
|
||||
`bad mac address length 2, allowed: [6 8 20]`,
|
||||
}, {
|
||||
lease: &Lease{
|
||||
lease: &dhcpsvc.Lease{
|
||||
Hostname: "bad-lbl-.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -266,7 +267,7 @@ func TestV4Server_AddRemove_static(t *testing.T) {
|
||||
return
|
||||
}
|
||||
|
||||
err = s.RemoveStaticLease(&Lease{
|
||||
err = s.RemoveStaticLease(&dhcpsvc.Lease{
|
||||
IP: tc.lease.IP,
|
||||
HWAddr: tc.lease.HWAddr,
|
||||
})
|
||||
@@ -289,7 +290,7 @@ func TestV4_AddReplace(t *testing.T) {
|
||||
s, ok := sIface.(*v4Server)
|
||||
require.True(t, ok)
|
||||
|
||||
dynLeases := []Lease{{
|
||||
dynLeases := []dhcpsvc.Lease{{
|
||||
Hostname: "dynamic-1.local",
|
||||
HWAddr: net.HardwareAddr{0x11, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -304,7 +305,7 @@ func TestV4_AddReplace(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
stLeases := []*Lease{{
|
||||
stLeases := []*dhcpsvc.Lease{{
|
||||
Hostname: "static-1.local",
|
||||
HWAddr: net.HardwareAddr{0x33, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -513,7 +514,7 @@ func TestV4StaticLease_Get(t *testing.T) {
|
||||
s.conf.dnsIPAddrs = []netip.Addr{dnsAddr}
|
||||
s.implicitOpts.Update(dhcpv4.OptDNS(dnsAddr.AsSlice()))
|
||||
|
||||
l := &Lease{
|
||||
l := &dhcpsvc.Lease{
|
||||
Hostname: "static-1.local",
|
||||
HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA},
|
||||
IP: netip.MustParseAddr("192.168.10.150"),
|
||||
@@ -779,7 +780,7 @@ func TestV4Server_FindMACbyIP(t *testing.T) {
|
||||
anotherMAC := net.HardwareAddr{0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB}
|
||||
|
||||
s := &v4Server{
|
||||
leases: []*Lease{{
|
||||
leases: []*dhcpsvc.Lease{{
|
||||
Hostname: staticName,
|
||||
HWAddr: staticMAC,
|
||||
IP: staticIP,
|
||||
@@ -791,11 +792,11 @@ func TestV4Server_FindMACbyIP(t *testing.T) {
|
||||
IP: anotherIP,
|
||||
}},
|
||||
}
|
||||
s.ipIndex = map[netip.Addr]*Lease{
|
||||
s.ipIndex = map[netip.Addr]*dhcpsvc.Lease{
|
||||
staticIP: s.leases[0],
|
||||
anotherIP: s.leases[1],
|
||||
}
|
||||
s.hostsIndex = map[string]*Lease{
|
||||
s.hostsIndex = map[string]*dhcpsvc.Lease{
|
||||
staticName: s.leases[0],
|
||||
anotherName: s.leases[1],
|
||||
}
|
||||
@@ -845,7 +846,7 @@ func TestV4Server_handleDecline(t *testing.T) {
|
||||
s4, ok := s.(*v4Server)
|
||||
require.True(t, ok)
|
||||
|
||||
s4.leases = []*Lease{{
|
||||
s4.leases = []*dhcpsvc.Lease{{
|
||||
Hostname: dynamicName,
|
||||
HWAddr: dynamicMAC,
|
||||
IP: dynamicIP,
|
||||
@@ -887,7 +888,7 @@ func TestV4Server_handleRelease(t *testing.T) {
|
||||
s4, ok := s.(*v4Server)
|
||||
require.True(t, ok)
|
||||
|
||||
s4.leases = []*Lease{{
|
||||
s4.leases = []*dhcpsvc.Lease{{
|
||||
Hostname: dynamicName,
|
||||
HWAddr: dynamicMAC,
|
||||
IP: dynamicIP,
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/golibs/errors"
|
||||
"github.com/AdguardTeam/golibs/log"
|
||||
"github.com/AdguardTeam/golibs/netutil"
|
||||
@@ -31,7 +32,7 @@ type v6Server struct {
|
||||
sid dhcpv6.DUID
|
||||
srv *server6.Server
|
||||
|
||||
leases []*Lease
|
||||
leases []*dhcpsvc.Lease
|
||||
leasesLock sync.Mutex
|
||||
ipAddrs [256]byte
|
||||
}
|
||||
@@ -87,7 +88,7 @@ func (s *v6Server) IPByHost(host string) (ip netip.Addr) {
|
||||
}
|
||||
|
||||
// ResetLeases resets leases.
|
||||
func (s *v6Server) ResetLeases(leases []*Lease) (err error) {
|
||||
func (s *v6Server) ResetLeases(leases []*dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv6: %w") }()
|
||||
|
||||
s.leasesLock.Lock()
|
||||
@@ -111,12 +112,14 @@ func (s *v6Server) ResetLeases(leases []*Lease) (err error) {
|
||||
|
||||
// GetLeases returns the list of current DHCP leases. It is safe for concurrent
|
||||
// use.
|
||||
func (s *v6Server) GetLeases(flags GetLeasesFlags) (leases []*Lease) {
|
||||
func (s *v6Server) GetLeases(flags GetLeasesFlags) (leases []*dhcpsvc.Lease) {
|
||||
// The function shouldn't return nil value because zero-length slice
|
||||
// behaves differently in cases like marshalling. Our front-end also
|
||||
// requires non-nil value in the response.
|
||||
leases = []*Lease{}
|
||||
leases = []*dhcpsvc.Lease{}
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
for _, l := range s.leases {
|
||||
if l.IsStatic {
|
||||
if (flags & LeasesStatic) != 0 {
|
||||
@@ -128,12 +131,12 @@ func (s *v6Server) GetLeases(flags GetLeasesFlags) (leases []*Lease) {
|
||||
}
|
||||
}
|
||||
}
|
||||
s.leasesLock.Unlock()
|
||||
|
||||
return leases
|
||||
}
|
||||
|
||||
// getLeasesRef returns the actual leases slice. For internal use only.
|
||||
func (s *v6Server) getLeasesRef() []*Lease {
|
||||
func (s *v6Server) getLeasesRef() []*dhcpsvc.Lease {
|
||||
return s.leases
|
||||
}
|
||||
|
||||
@@ -174,7 +177,7 @@ func (s *v6Server) leaseRemoveSwapByIndex(i int) {
|
||||
|
||||
// Remove a dynamic lease with the same properties
|
||||
// Return error if a static lease is found
|
||||
func (s *v6Server) rmDynamicLease(lease *Lease) (err error) {
|
||||
func (s *v6Server) rmDynamicLease(lease *dhcpsvc.Lease) (err error) {
|
||||
for i := 0; i < len(s.leases); i++ {
|
||||
l := s.leases[i]
|
||||
|
||||
@@ -204,7 +207,7 @@ func (s *v6Server) rmDynamicLease(lease *Lease) (err error) {
|
||||
}
|
||||
|
||||
// AddStaticLease adds a static lease. It is safe for concurrent use.
|
||||
func (s *v6Server) AddStaticLease(l *Lease) (err error) {
|
||||
func (s *v6Server) AddStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv6: %w") }()
|
||||
|
||||
if !l.IP.Is6() {
|
||||
@@ -236,7 +239,7 @@ func (s *v6Server) AddStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// UpdateStaticLease updates IP, hostname of the static lease.
|
||||
func (s *v6Server) UpdateStaticLease(l *Lease) (err error) {
|
||||
func (s *v6Server) UpdateStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() {
|
||||
if err != nil {
|
||||
err = errors.Annotate(err, "dhcpv6: updating static lease: %w")
|
||||
@@ -267,7 +270,7 @@ func (s *v6Server) UpdateStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// RemoveStaticLease removes a static lease. It is safe for concurrent use.
|
||||
func (s *v6Server) RemoveStaticLease(l *Lease) (err error) {
|
||||
func (s *v6Server) RemoveStaticLease(l *dhcpsvc.Lease) (err error) {
|
||||
defer func() { err = errors.Annotate(err, "dhcpv6: %w") }()
|
||||
|
||||
if !l.IP.Is6() {
|
||||
@@ -292,7 +295,7 @@ func (s *v6Server) RemoveStaticLease(l *Lease) (err error) {
|
||||
}
|
||||
|
||||
// Add a lease
|
||||
func (s *v6Server) addLease(l *Lease) {
|
||||
func (s *v6Server) addLease(l *dhcpsvc.Lease) {
|
||||
s.leases = append(s.leases, l)
|
||||
ip := l.IP.As16()
|
||||
s.ipAddrs[ip[15]] = 1
|
||||
@@ -300,7 +303,7 @@ func (s *v6Server) addLease(l *Lease) {
|
||||
}
|
||||
|
||||
// Remove a lease with the same properties
|
||||
func (s *v6Server) rmLease(lease *Lease) (err error) {
|
||||
func (s *v6Server) rmLease(lease *dhcpsvc.Lease) (err error) {
|
||||
for i, l := range s.leases {
|
||||
if l.IP == lease.IP {
|
||||
if !bytes.Equal(l.HWAddr, lease.HWAddr) ||
|
||||
@@ -318,7 +321,7 @@ func (s *v6Server) rmLease(lease *Lease) (err error) {
|
||||
}
|
||||
|
||||
// Find lease by MAC.
|
||||
func (s *v6Server) findLease(mac net.HardwareAddr) (lease *Lease) {
|
||||
func (s *v6Server) findLease(mac net.HardwareAddr) (lease *dhcpsvc.Lease) {
|
||||
for i := range s.leases {
|
||||
if bytes.Equal(mac, s.leases[i].HWAddr) {
|
||||
return s.leases[i]
|
||||
@@ -356,8 +359,8 @@ func (s *v6Server) findFreeIP() net.IP {
|
||||
}
|
||||
|
||||
// Reserve lease for MAC
|
||||
func (s *v6Server) reserveLease(mac net.HardwareAddr) *Lease {
|
||||
l := Lease{
|
||||
func (s *v6Server) reserveLease(mac net.HardwareAddr) *dhcpsvc.Lease {
|
||||
l := dhcpsvc.Lease{
|
||||
HWAddr: make([]byte, len(mac)),
|
||||
}
|
||||
|
||||
@@ -390,7 +393,7 @@ func (s *v6Server) reserveLease(mac net.HardwareAddr) *Lease {
|
||||
return &l
|
||||
}
|
||||
|
||||
func (s *v6Server) commitDynamicLease(l *Lease) {
|
||||
func (s *v6Server) commitDynamicLease(l *dhcpsvc.Lease) {
|
||||
l.Expiry = time.Now().Add(s.conf.leaseTime)
|
||||
|
||||
s.leasesLock.Lock()
|
||||
@@ -438,7 +441,7 @@ func (s *v6Server) checkSID(msg *dhcpv6.Message) error {
|
||||
}
|
||||
|
||||
// . IAAddress must be equal to the lease's IP
|
||||
func (s *v6Server) checkIA(msg *dhcpv6.Message, lease *Lease) error {
|
||||
func (s *v6Server) checkIA(msg *dhcpv6.Message, lease *dhcpsvc.Lease) error {
|
||||
switch msg.Type() {
|
||||
case dhcpv6.MessageTypeRequest,
|
||||
dhcpv6.MessageTypeConfirm,
|
||||
@@ -464,7 +467,7 @@ func (s *v6Server) checkIA(msg *dhcpv6.Message, lease *Lease) error {
|
||||
}
|
||||
|
||||
// Store lease in DB (if necessary) and return lease life time
|
||||
func (s *v6Server) commitLease(msg *dhcpv6.Message, lease *Lease) time.Duration {
|
||||
func (s *v6Server) commitLease(msg *dhcpv6.Message, lease *dhcpsvc.Lease) time.Duration {
|
||||
lifetime := s.conf.leaseTime
|
||||
|
||||
switch msg.Type() {
|
||||
@@ -506,7 +509,7 @@ func (s *v6Server) process(msg *dhcpv6.Message, req, resp dhcpv6.DHCPv6) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
var lease *Lease
|
||||
var lease *dhcpsvc.Lease
|
||||
func() {
|
||||
s.leasesLock.Lock()
|
||||
defer s.leasesLock.Unlock()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user