milestone 11: systemd and docker packaging, operator and architecture docs, config and api reference, docs drift guards
This commit is contained in:
+31
-14
@@ -199,21 +199,20 @@ const max_rate_window_seconds = 3_600;
|
||||
|
||||
fn checkScalars(cfg: Config, diags: *Diagnostics) error{OutOfMemory}!void {
|
||||
const up = cfg.upstream;
|
||||
try checkTimeout(diags, up.connect_timeout_ms, "upstream.connect_timeout_ms");
|
||||
try checkTimeout(diags, up.read_timeout_ms, "upstream.read_timeout_ms");
|
||||
try checkTimeout(diags, up.total_timeout_ms, "upstream.total_timeout_ms");
|
||||
if (up.total_timeout_ms < up.connect_timeout_ms or up.total_timeout_ms < up.read_timeout_ms) {
|
||||
if (up.total_timeout_ms < up.read_timeout_ms) {
|
||||
try diags.add(
|
||||
error.BadTimeout,
|
||||
"upstream.total_timeout_ms",
|
||||
.{},
|
||||
"total budget {d}ms is below connect {d}ms or read {d}ms",
|
||||
.{ up.total_timeout_ms, up.connect_timeout_ms, up.read_timeout_ms },
|
||||
"total budget {d}ms is below read {d}ms",
|
||||
.{ up.total_timeout_ms, up.read_timeout_ms },
|
||||
);
|
||||
}
|
||||
|
||||
try checkBind(diags, cfg.dns.bind_ipv4, "dns.bind_ipv4", true);
|
||||
try checkBind(diags, cfg.dns.bind_ipv6, "dns.bind_ipv6", false);
|
||||
try checkBind(diags, cfg.dns.bind_ipv4, "dns.bind_ipv4", .ip4);
|
||||
try checkBind(diags, cfg.dns.bind_ipv6, "dns.bind_ipv6", .ip6);
|
||||
try checkPort(diags, cfg.dns.port, "dns.port");
|
||||
if (cfg.dns.rate_limit < 1) {
|
||||
try diags.add(error.BadRateLimit, "dns.rate_limit", .{}, "must be at least 1", .{});
|
||||
@@ -248,7 +247,7 @@ fn checkScalars(cfg: Config, diags: *Diagnostics) error{OutOfMemory}!void {
|
||||
);
|
||||
}
|
||||
|
||||
try checkBind(diags, cfg.web.bind, "web.bind", false);
|
||||
try checkBind(diags, cfg.web.bind, "web.bind", .any);
|
||||
try checkPort(diags, cfg.web.port, "web.port");
|
||||
if (cfg.web.password.len != 0 and cfg.web.password_hash.len != 0) {
|
||||
try diags.add(
|
||||
@@ -339,18 +338,30 @@ fn checkTimeout(diags: *Diagnostics, value: u32, comptime path: []const u8) erro
|
||||
}
|
||||
}
|
||||
|
||||
const BindFamily = enum { ip4, ip6, any };
|
||||
|
||||
/// `dns.bind_ipv4` and `dns.bind_ipv6` each name one socket of the dual-stack
|
||||
/// pair, so each must be a literal of its own family: an IPv4 wildcard in
|
||||
/// `bind_ipv6` would bind IPv4 as the "v6" socket and make the real IPv4 bind
|
||||
/// fail with AddressInUse — the IPv6 service silently disappears.
|
||||
fn checkBind(
|
||||
diags: *Diagnostics,
|
||||
text: []const u8,
|
||||
comptime path: []const u8,
|
||||
comptime require_ip4: bool,
|
||||
comptime family: BindFamily,
|
||||
) error{OutOfMemory}!void {
|
||||
const addr = NetAddress.parse(text) catch {
|
||||
try diags.add(error.BadBindAddress, path, .{}, "'{s}' is not an IP address", .{text});
|
||||
return;
|
||||
};
|
||||
if (require_ip4 and std.meta.activeTag(addr) != NetAddress.ip4) {
|
||||
try diags.add(error.BadBindAddress, path, .{}, "'{s}' is not an IPv4 address", .{text});
|
||||
switch (family) {
|
||||
.ip4 => if (std.meta.activeTag(addr) != NetAddress.ip4) {
|
||||
try diags.add(error.BadBindAddress, path, .{}, "'{s}' is not an IPv4 address", .{text});
|
||||
},
|
||||
.ip6 => if (std.meta.activeTag(addr) != NetAddress.ip6) {
|
||||
try diags.add(error.BadBindAddress, path, .{}, "'{s}' is not an IPv6 address", .{text});
|
||||
},
|
||||
.any => {},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,7 +370,7 @@ fn checkTlsEndpoint(
|
||||
endpoint: model.TlsEndpoint,
|
||||
comptime section: []const u8,
|
||||
) error{OutOfMemory}!void {
|
||||
try checkBind(diags, endpoint.bind, section ++ ".bind", false);
|
||||
try checkBind(diags, endpoint.bind, section ++ ".bind", .any);
|
||||
try checkPort(diags, endpoint.port, section ++ ".port");
|
||||
if (!endpoint.enabled) return;
|
||||
// Readability of the files is `nxdns check`'s job, not the pure validator's.
|
||||
@@ -1162,11 +1173,11 @@ test "error.BadPort" {
|
||||
|
||||
test "error.BadTimeout" {
|
||||
var cfg = baseConfig();
|
||||
cfg.upstream.connect_timeout_ms = 10;
|
||||
try expectProblem(cfg, error.BadTimeout, "upstream.connect_timeout_ms");
|
||||
cfg.upstream.read_timeout_ms = 10;
|
||||
try expectProblem(cfg, error.BadTimeout, "upstream.read_timeout_ms");
|
||||
|
||||
var budget = baseConfig();
|
||||
budget.upstream = .{ .connect_timeout_ms = 4000, .read_timeout_ms = 4000, .total_timeout_ms = 1000 };
|
||||
budget.upstream = .{ .read_timeout_ms = 4000, .total_timeout_ms = 1000 };
|
||||
try expectProblem(budget, error.BadTimeout, "upstream.total_timeout_ms");
|
||||
}
|
||||
|
||||
@@ -1214,6 +1225,12 @@ test "error.BadBindAddress" {
|
||||
try expectProblem(web, error.BadBindAddress, "web.bind");
|
||||
}
|
||||
|
||||
test "error.BadBindAddress on an IPv4 literal in dns.bind_ipv6" {
|
||||
var cfg = baseConfig();
|
||||
cfg.dns.bind_ipv6 = "0.0.0.0";
|
||||
try expectProblem(cfg, error.BadBindAddress, "dns.bind_ipv6");
|
||||
}
|
||||
|
||||
test "error.MissingCertPath" {
|
||||
var cfg = baseConfig();
|
||||
cfg.doh_server = .{ .enabled = true, .cert_path = "" };
|
||||
|
||||
Reference in New Issue
Block a user