Files
NeoTachyon/tachyon/files/usr/lib/providers/adguard/validator.uc
T
hacker07 617107ef15 feat(adguard): add AdGuard Home component with DNS modes, failover and section upstream
Add AdGuard Home as an installable Tachyon component (component card with
check/update/remove/rollback/enable/disable) backed by providers/adguard
(validator + runtime) and an init.d service.

Backend:
- action.uc: install/remove/enable/backup/rollback/dispatch/releases for
  'adguard' (tar.gz from AdguardTeam/AdGuardHome, OpenWrt->AdGuard arch map)
- updater.uc: adguard asset selection; updates.uc: valid_component_name and
  automatic update checks
- runtime.uc: generates AdGuardHome.yaml from UCI (upstream=single-box DNS,
  fallback_dns for failover, web UI on LAN, filters), manages the daemon
- dns/apply.uc: dns_main_mode (dnsmasq->AdGuard->sing-box chain, or AdGuard on
  :53 with dnsmasq DHCP-only)
- settings: dns_main_mode (Main DNS) + dns_adguard_failover_enabled
- sections: routed_dns_type/dns_type 'adguard' resolve via the AdGuard provider
  upstreams; validator accepts the new type
- system-info: adguard_version/installed/enabled/backup fields

Frontend:
- component card 'AdGuard Home' with enable/disable + version actions
- LuCI DNS settings tab: Main DNS selector and failover flag
- section.js: AdGuard Home routed DNS protocol option

Tests: tests/adguard_validator.sh, tests/adguard_runtime.sh
2026-09-17 14:22:13 +03:00

113 lines
3.5 KiB
Ucode

#!/usr/bin/env ucode
let common = require("core.common");
let as_string = common.as_string;
function write_json(value) {
print(sprintf("%J", value), "\n");
}
function words(value) {
value = replace(as_string(value), /[\t\r\n]/g, " ");
value = replace(value, / +/g, " ");
value = replace(value, /^ /, "");
value = replace(value, / $/, "");
return value == "" ? [] : split(value, " ");
}
function contains(values, needle) {
for (let value in values)
if (as_string(value) == as_string(needle))
return true;
return false;
}
function valid_port(value) {
value = as_string(value);
return value != "" && match(value, /^[0-9]+$/) != null &&
int(value) >= 1 && int(value) <= 65535;
}
// Upstream DNS accepted forms:
// - plain IP[:port] e.g. 1.1.1.1, 8.8.8.8:53
// - https://host[/dns-query] DoH
// - tls://host[:port] DoT
// - quic://host[:port] DoQ
// - udp://host[:port] explicit plain
function validate_upstream(value) {
value = trim(as_string(value));
if (value == "")
return { valid: false, message: "Empty DNS server" };
if (match(value, /^https:\/\//) != null)
return match(value, /^https:\/\/[^\s\/]+\//) != null || match(value, /^https:\/\/[^\s\/]+$/) != null
? { valid: true, message: "" }
: { valid: false, message: "Invalid DoH URL: " + value };
if (match(value, /^tls:\/\//) != null || match(value, /^quic:\/\//) != null)
return { valid: true, message: "" };
if (match(value, /^udp:\/\//) != null)
value = substr(value, 6);
let hostport = value;
let colon = rindex(hostport, ":");
let host = "";
let port = "";
if (colon >= 0 && index(hostport, "]") < 0) {
host = substr(hostport, 0, colon);
port = substr(hostport, colon + 1);
} else {
host = hostport;
}
if (host == "")
return { valid: false, message: "Empty DNS host" };
if (port != "" && !valid_port(port))
return { valid: false, message: "Invalid DNS port in: " + value };
return { valid: true, message: "" };
}
function validate_upstreams(values) {
for (let value in (type(values) == "array" ? values : [])) {
let result = validate_upstream(value);
if (!result.valid)
return result;
}
return { valid: true, message: "" };
}
function dns_main_mode_valid(mode) {
mode = as_string(mode);
return mode == "dnsmasq" || mode == "adguard";
}
function print_dns_main_mode_valid(mode) {
exit(dns_main_mode_valid(mode) ? 0 : 1);
}
function validate_filter_url(value) {
value = trim(as_string(value));
if (value == "")
return { valid: false, message: "Empty filter list URL" };
return match(value, /^https?:\/\//) != null
? { valid: true, message: "" }
: { valid: false, message: "Filter list must be an http(s) URL: " + value };
}
let mode = ARGV[0] || "";
if (mode == "validate-upstream")
write_json(validate_upstream(ARGV[1]));
else if (mode == "validate-upstreams")
write_json(validate_upstreams(ARGV[1] != null ? [ ARGV[1] ] : []));
else if (mode == "validate-filter-url")
write_json(validate_filter_url(ARGV[1]));
else if (mode == "dns-main-mode-valid")
print_dns_main_mode_valid(ARGV[1]);
else if (mode == "valid-port")
exit(valid_port(ARGV[1]) ? 0 : 1);
else {
warn("Usage: providers/adguard/validator.uc <validate-upstream|validate-filter-url|dns-main-mode-valid|valid-port> ...\n");
exit(1);
}