From 7965fc669bdf71cd9a85a475cc5931a01f0cbfcf Mon Sep 17 00:00:00 2001 From: Alex Hope-O'Connor Date: Wed, 11 Feb 2026 12:29:15 +1000 Subject: [PATCH] Implement remaining dnsmasq config options and add parser tests - Add DnsmasqConfKeys for DHCP advanced, DHCPv6/RA, TFTP/PXE, DNSSEC, Other - Add EffectiveDnsmasqConfig + EffectiveConfigSources for new options - Wire ConfigSetCache BuildEffectiveConfig/Sources/CreateDefault - Add EffectiveConfigFieldBuilder sections (TFTP/PXE, DNSSEC), tooltips, registry - Update EffectiveDnsmasqConfigTests CreateConfig with all new params - Add one parser test per conf option with documented example (200 tests) --- .../DnsmasqConfIncludeParserTests.cs | 1518 +++++++++++++++++ .../EffectiveDnsmasqConfigTests.cs | 24 +- .../EffectiveConfigSection.razor | 3 + .../Helpers/Config/DnsmasqConfKeys.cs | 30 + .../Helpers/Config/DnsmasqOptionTooltips.cs | 35 + .../Config/EffectiveConfigFieldBuilder.cs | 64 +- .../Infrastructure/Services/ConfigSetCache.cs | 189 +- .../EffectiveConfigRenderFragmentRegistry.cs | 4 + .../EffectiveConfig/EffectiveConfigSources.cs | 31 +- .../EffectiveConfig/EffectiveDnsmasqConfig.cs | 31 +- 10 files changed, 1894 insertions(+), 35 deletions(-) diff --git a/src/DnsmasqWebUI.Tests/DnsmasqConfIncludeParserTests.cs b/src/DnsmasqWebUI.Tests/DnsmasqConfIncludeParserTests.cs index d5cef5d..52e9415 100644 --- a/src/DnsmasqWebUI.Tests/DnsmasqConfIncludeParserTests.cs +++ b/src/DnsmasqWebUI.Tests/DnsmasqConfIncludeParserTests.cs @@ -745,4 +745,1522 @@ public class DnsmasqConfIncludeParserTests Directory.Delete(dir, recursive: true); } } + + // --- Phase 4: one test per new option with a real dnsmasq example --- + + [Fact] + public void GetLastValueFromConfigFiles_Hostsdir_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-hostsdir-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var path = "/etc/dnsmasq.d/hosts"; + try + { + File.WriteAllText(conf, $"hostsdir={path}\n"); + var (value, configDir) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Hostsdir); + Assert.Equal(path, value); + Assert.Equal(dir, configDir); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_Domain_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-domain-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "home,192.168.1.1"; + try + { + File.WriteAllText(conf, $"domain={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Domain); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_Cname_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-cname-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "mail.example.com,real.example.com"; + try + { + File.WriteAllText(conf, $"cname={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Cname); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_MxHost_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-mx-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "example.com,mail.example.com,50"; + try + { + File.WriteAllText(conf, $"mx-host={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MxHost); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_Srv_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-srv-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "_http._tcp.example.com,server.example.com,80"; + try + { + File.WriteAllText(conf, $"srv={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Srv); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_PtrRecord_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-ptr-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "1.168.192.in-addr.arpa,host.example.com"; + try + { + File.WriteAllText(conf, $"ptr-record={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.PtrRecord); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_TxtRecord_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-txt-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "example.com,v=spf1 include:_spf.example.com"; + try + { + File.WriteAllText(conf, $"txt-record={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.TxtRecord); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_NaptrRecord_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-naptr-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "example.com,100,10,u,sip+E2U,sips:.*@example.com,."; + try + { + File.WriteAllText(conf, $"naptr-record={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NaptrRecord); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_HostRecord_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-hostrecord-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "router.example.com,192.168.1.1"; + try + { + File.WriteAllText(conf, $"host-record={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.HostRecord); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DynamicHost_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dynamichost-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "hostname,example.com,192.168.1.50"; + try + { + File.WriteAllText(conf, $"dynamic-host={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DynamicHost); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_InterfaceName_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-ifname-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "eth0,router.local"; + try + { + File.WriteAllText(conf, $"interface-name={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.InterfaceName); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + // --- Remaining options: one test per new option with a real dnsmasq example --- + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpMatch_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpmatch-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "set:bios,option:client-arch,0"; + try + { + File.WriteAllText(conf, $"dhcp-match={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpMatch); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpBoot_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpboot-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "tag:bios-x86,firmware/ipxe.pxe,192.168.1.1"; + try + { + File.WriteAllText(conf, $"dhcp-boot={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpBoot); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpIgnore_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpignore-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "tag:!known"; + try + { + File.WriteAllText(conf, $"dhcp-ignore={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpIgnore); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpVendorclass_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpvc-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "set:pxe,option:vendor-class-identifier,PXEClient"; + try + { + File.WriteAllText(conf, $"dhcp-vendorclass={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpVendorclass); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpUserclass_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpuc-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "set:ipxe,iPXE"; + try + { + File.WriteAllText(conf, $"dhcp-userclass={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpUserclass); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_RaParam_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-raparam-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "eth0,high,0"; + try + { + File.WriteAllText(conf, $"ra-param={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.RaParam); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_Slaac_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-slaac-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "eth0,0"; + try + { + File.WriteAllText(conf, $"slaac={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Slaac); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_EnableTftp_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-tftp-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "enable-tftp\n"); + var result = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.EnableTftp); + Assert.True(result); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_TftpRoot_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-tftproot-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var path = "/var/lib/tftpboot"; + try + { + File.WriteAllText(conf, $"tftp-root={path}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.TftpRoot); + Assert.Equal(path, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_TftpSecure_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-tftpsec-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "tftp-secure\n"); + var result = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.TftpSecure); + Assert.True(result); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_PxeService_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-pxe-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "x86PC,pxelinux.0"; + try + { + File.WriteAllText(conf, $"pxe-service={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.PxeService); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_PxePrompt_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-pxeprompt-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "timeout,0"; + try + { + File.WriteAllText(conf, $"pxe-prompt={line}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.PxePrompt); + Assert.Equal(line, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_Dnssec_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dnssec-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dnssec\n"); + var result = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Dnssec); + Assert.True(result); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_TrustAnchor_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-trust-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = ". IN DS 19036 8 2 49AAC11D7B6F6446702E54A1607371607A1A41855200FD2CE1CDE32F024E8FC5"; + try + { + File.WriteAllText(conf, $"trust-anchor={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.TrustAnchor); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_DnssecCheckUnsigned_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dnsseccu-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dnssec-check-unsigned\n"); + var result = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DnssecCheckUnsigned); + Assert.True(result); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_EnableDbus_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dbus-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var svc = "org.freedesktop.NetworkManager"; + try + { + File.WriteAllText(conf, $"enable-dbus={svc}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.EnableDbus); + Assert.Equal(svc, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_EnableUbus_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-ubus-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var svc = "com.example.dnsmasq"; + try + { + File.WriteAllText(conf, $"enable-ubus={svc}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.EnableUbus); + Assert.Equal(svc, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_FastDnsRetry_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-fastretry-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "500,5000"; + try + { + File.WriteAllText(conf, $"fast-dns-retry={line}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.FastDnsRetry); + Assert.Equal(line, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + // --- Additional tests: one per conf field so every option has a documented example test --- + + [Fact] + public void GetMultiValueFromConfigFiles_Interface_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-if-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "interface=eth0\ninterface=wlan0\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Interface); + Assert.Equal(2, result.Count); + Assert.Equal("eth0", result[0]); + Assert.Equal("wlan0", result[1]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_ExceptInterface_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-except-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "except-interface=eth1\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.ExceptInterface); + Assert.Single(result); + Assert.Equal("eth1", result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_NoDhcpInterface_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-nodhcpi-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-dhcp-interface=eth2\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoDhcpInterface); + Assert.Single(result); + Assert.Equal("eth2", result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_NoDhcpv4Interface_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-nodhcp4-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-dhcpv4-interface=eth0\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoDhcpv4Interface); + Assert.Single(result); + Assert.Equal("eth0", result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_NoDhcpv6Interface_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-nodhcp6-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-dhcpv6-interface=eth0\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoDhcpv6Interface); + Assert.Single(result); + Assert.Equal("eth0", result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_AuthServer_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-auth-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "lan,eth0"; + try + { + File.WriteAllText(conf, $"auth-server={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.AuthServer); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpHost_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcphost-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "00:11:22:33:44:55,192.168.1.100,router,12h"; + try + { + File.WriteAllText(conf, $"dhcp-host={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpHost); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_DhcpOption_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpopt-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "option:router,192.168.1.1"; + try + { + File.WriteAllText(conf, $"dhcp-option={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpOption); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_ResolvFile_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-resolv-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var path = "/etc/resolv.dnsmasq"; + try + { + File.WriteAllText(conf, $"resolv-file={path}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.ResolvFile); + Assert.Single(result); + Assert.Equal(path, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_RebindDomainOk_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-rebind-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "/local.lan/"; + try + { + File.WriteAllText(conf, $"rebind-domain-ok={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.RebindDomainOk); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_BogusNxdomain_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-bogusnx-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "64.94.110.11"; + try + { + File.WriteAllText(conf, $"bogus-nxdomain={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.BogusNxdomain); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_IgnoreAddress_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-ignoreaddr-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "192.168.1.0/24"; + try + { + File.WriteAllText(conf, $"ignore-address={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.IgnoreAddress); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_Alias_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-alias-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "1.2.3.0,6.7.8.0,255.255.255.0"; + try + { + File.WriteAllText(conf, $"alias={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Alias); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_FilterRr_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-filterrr-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "TXT,MX"; + try + { + File.WriteAllText(conf, $"filter-rr={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.FilterRr); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetMultiValueFromConfigFiles_CacheRr_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-cacherr-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var line = "TXT"; + try + { + File.WriteAllText(conf, $"cache-rr={line}\n"); + var result = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.CacheRr); + Assert.Single(result); + Assert.Equal(line, result[0]); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_NoHosts_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-nohosts-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-hosts\n"); + var result = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoHosts); + Assert.True(result); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_BogusPriv_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-boguspriv-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "bogus-priv\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.BogusPriv)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_StrictOrder_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-strict-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "strict-order\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.StrictOrder)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_DomainNeeded_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-domainneed-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "domain-needed\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DomainNeeded)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_NoPoll_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-nopoll-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-poll\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoPoll)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_BindInterfaces_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-bindif-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "bind-interfaces\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.BindInterfaces)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_BindDynamic_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-binddyn-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "bind-dynamic\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.BindDynamic)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_NoNegcache_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-noneg-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "no-negcache\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NoNegcache)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_DnsLoopDetect_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-loop-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dns-loop-detect\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DnsLoopDetect)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_StopDnsRebind_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-rebind-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "stop-dns-rebind\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.StopDnsRebind)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_RebindLocalhostOk_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-rebindlo-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "rebind-localhost-ok\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.RebindLocalhostOk)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_ClearOnReload_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-clear-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "clear-on-reload\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.ClearOnReload)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_Filterwin2k_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-filtw2k-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "filterwin2k\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Filterwin2k)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_FilterA_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-filta-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "filter-A\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.FilterA)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_FilterAaaa_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-filtaaaa-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "filter-AAAA\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.FilterAaaa)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_LocaliseQueries_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-localise-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "localise-queries\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LocaliseQueries)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_LogDebug_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-logdbg-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "log-debug\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LogDebug)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_DhcpAuthoritative_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpauth-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dhcp-authoritative\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpAuthoritative)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetFlagFromConfigFiles_LeasefileRo_WhenPresent_ReturnsTrue() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-leasero-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "leasefile-ro\n"); + Assert.True(DnsmasqConfIncludeParser.GetFlagFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LeasefileRo)); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_LocalTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-localttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "local-ttl=300\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LocalTtl); + Assert.Equal("300", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_PidFile_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-pid-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + var path = "/var/run/dnsmasq.pid"; + try + { + File.WriteAllText(conf, $"pid-file={path}\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.PidFile); + Assert.Equal(path, value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_User_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-user-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "user=nobody\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.User); + Assert.Equal("nobody", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_Group_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-group-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "group=dip\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.Group); + Assert.Equal("dip", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_AuthTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-authttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "auth-ttl=60\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.AuthTtl); + Assert.Equal("60", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_EdnsPacketMax_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-edns-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "edns-packet-max=1232\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.EdnsPacketMax); + Assert.Equal("1232", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_QueryPort_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-qport-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "query-port=0\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.QueryPort); + Assert.Equal("0", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_PortLimit_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-portlimit-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "port-limit=3\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.PortLimit); + Assert.Equal("3", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_MinPort_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-minport-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "min-port=1024\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MinPort); + Assert.Equal("1024", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_MaxPort_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-maxport-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "max-port=65535\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MaxPort); + Assert.Equal("65535", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_LogAsync_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-logasync-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "log-async=25\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LogAsync); + Assert.Equal("25", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_LocalService_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-localsvc-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "local-service=host\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.LocalService); + Assert.Equal("host", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_DhcpLeaseMax_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-leasemax-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dhcp-lease-max=150\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpLeaseMax); + Assert.Equal("150", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_NegTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-negttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "neg-ttl=60\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.NegTtl); + Assert.Equal("60", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_MaxTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-maxttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "max-ttl=3600\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MaxTtl); + Assert.Equal("3600", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_MaxCacheTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-maxcttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "max-cache-ttl=86400\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MaxCacheTtl); + Assert.Equal("86400", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_MinCacheTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-mincttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "min-cache-ttl=60\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.MinCacheTtl); + Assert.Equal("60", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } + + [Fact] + public void GetLastValueFromConfigFiles_DhcpTtl_ParsesRealExample() + { + var dir = Path.Combine(Path.GetTempPath(), "dnsmasq-dhcpttl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(dir); + var conf = Path.Combine(dir, "dnsmasq.conf"); + try + { + File.WriteAllText(conf, "dhcp-ttl=0\n"); + var (value, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(new[] { conf }, DnsmasqConfKeys.DhcpTtl); + Assert.Equal("0", value); + } + finally + { + Directory.Delete(dir, recursive: true); + } + } } diff --git a/src/DnsmasqWebUI.Tests/EffectiveDnsmasqConfigTests.cs b/src/DnsmasqWebUI.Tests/EffectiveDnsmasqConfigTests.cs index 3084163..d80a3bb 100644 --- a/src/DnsmasqWebUI.Tests/EffectiveDnsmasqConfigTests.cs +++ b/src/DnsmasqWebUI.Tests/EffectiveDnsmasqConfigTests.cs @@ -11,6 +11,7 @@ public class EffectiveDnsmasqConfigTests new( NoHosts: false, AddnHostsPaths: Array.Empty(), + HostsdirPath: null, ServerLocalValues: Array.Empty(), RevServerValues: Array.Empty(), AddressValues: Array.Empty(), @@ -20,6 +21,15 @@ public class EffectiveDnsmasqConfigTests DhcpRanges: Array.Empty(), DhcpHostLines: Array.Empty(), DhcpOptionLines: Array.Empty(), + DhcpMatchValues: Array.Empty(), + DhcpBootValues: Array.Empty(), + DhcpIgnoreValues: Array.Empty(), + DhcpVendorclassValues: Array.Empty(), + DhcpUserclassValues: Array.Empty(), + RaParamValues: Array.Empty(), + SlaacValues: Array.Empty(), + PxeServiceValues: Array.Empty(), + TrustAnchorValues: Array.Empty(), ResolvFiles: Array.Empty(), RebindDomainOkValues: Array.Empty(), BogusNxdomainValues: Array.Empty(), @@ -31,6 +41,9 @@ public class EffectiveDnsmasqConfigTests NoDhcpInterfaceValues: Array.Empty(), NoDhcpv4InterfaceValues: Array.Empty(), NoDhcpv6InterfaceValues: Array.Empty(), + DomainValues: Array.Empty(), CnameValues: Array.Empty(), MxHostValues: Array.Empty(), SrvValues: Array.Empty(), + PtrRecordValues: Array.Empty(), TxtRecordValues: Array.Empty(), NaptrRecordValues: Array.Empty(), + HostRecordValues: Array.Empty(), DynamicHostValues: Array.Empty(), InterfaceNameValues: Array.Empty(), ExpandHosts: false, BogusPriv: false, StrictOrder: false, @@ -52,6 +65,10 @@ public class EffectiveDnsmasqConfigTests LogDebug: false, DhcpAuthoritative: false, LeasefileRo: false, + EnableTftp: false, + TftpSecure: false, + Dnssec: false, + DnssecCheckUnsigned: false, DhcpLeaseFilePath: null, CacheSize: null, Port: null, @@ -74,7 +91,12 @@ public class EffectiveDnsmasqConfigTests MaxTtl: null, MaxCacheTtl: null, MinCacheTtl: null, - DhcpTtl: null + DhcpTtl: null, + TftpRootPath: null, + PxePrompt: null, + EnableDbus: null, + EnableUbus: null, + FastDnsRetry: null ); [Fact] diff --git a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigSection.razor b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigSection.razor index b26bd5f..7ad0d00 100644 --- a/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigSection.razor +++ b/src/DnsmasqWebUI/Components/Dnsmasq/EffectiveConfig/EffectiveConfigSection.razor @@ -10,7 +10,10 @@ { (EffectiveConfigFieldBuilder.SectionHosts, "Hosts"), (EffectiveConfigFieldBuilder.SectionResolver, "Resolver / DNS"), + (EffectiveConfigFieldBuilder.SectionDnsRecords, "DNS records"), (EffectiveConfigFieldBuilder.SectionDhcp, "DHCP"), + (EffectiveConfigFieldBuilder.SectionTftpPxe, "TFTP / PXE"), + (EffectiveConfigFieldBuilder.SectionDnssec, "DNSSEC"), (EffectiveConfigFieldBuilder.SectionCache, "Cache"), (EffectiveConfigFieldBuilder.SectionProcess, "Process & networking") }; diff --git a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqConfKeys.cs b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqConfKeys.cs index ede163d..d70a33e 100644 --- a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqConfKeys.cs +++ b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqConfKeys.cs @@ -14,6 +14,7 @@ public static class DnsmasqConfKeys // --- Hosts --- public const string NoHosts = "no-hosts"; public const string AddnHosts = "addn-hosts"; + public const string Hostsdir = "hostsdir"; // --- DHCP lease file (last wins) --- public const string DhcpLeasefile = "dhcp-leasefile"; @@ -34,6 +35,15 @@ public static class DnsmasqConfKeys public const string DhcpRange = "dhcp-range"; public const string DhcpHost = "dhcp-host"; public const string DhcpOption = "dhcp-option"; + public const string DhcpMatch = "dhcp-match"; + public const string DhcpBoot = "dhcp-boot"; + public const string DhcpIgnore = "dhcp-ignore"; + public const string DhcpVendorclass = "dhcp-vendorclass"; + public const string DhcpUserclass = "dhcp-userclass"; + public const string RaParam = "ra-param"; + public const string Slaac = "slaac"; + public const string PxeService = "pxe-service"; + public const string TrustAnchor = "trust-anchor"; public const string ResolvFile = "resolv-file"; public const string RebindDomainOk = "rebind-domain-ok"; public const string BogusNxdomain = "bogus-nxdomain"; @@ -41,6 +51,17 @@ public static class DnsmasqConfKeys public const string Alias = "alias"; public const string FilterRr = "filter-rr"; public const string CacheRr = "cache-rr"; + // --- DNS records (authoritative / local) --- + public const string Domain = "domain"; + public const string Cname = "cname"; + public const string MxHost = "mx-host"; + public const string Srv = "srv"; + public const string PtrRecord = "ptr-record"; + public const string TxtRecord = "txt-record"; + public const string NaptrRecord = "naptr-record"; + public const string HostRecord = "host-record"; + public const string DynamicHost = "dynamic-host"; + public const string InterfaceName = "interface-name"; // --- Flags (no value) --- public const string ExpandHosts = "expand-hosts"; @@ -64,6 +85,10 @@ public static class DnsmasqConfKeys public const string LogDebug = "log-debug"; public const string DhcpAuthoritative = "dhcp-authoritative"; public const string LeasefileRo = "leasefile-ro"; + public const string EnableTftp = "enable-tftp"; + public const string TftpSecure = "tftp-secure"; + public const string Dnssec = "dnssec"; + public const string DnssecCheckUnsigned = "dnssec-check-unsigned"; // --- Single-value (last wins) --- public const string CacheSize = "cache-size"; @@ -88,6 +113,11 @@ public static class DnsmasqConfKeys public const string MaxCacheTtl = "max-cache-ttl"; public const string MinCacheTtl = "min-cache-ttl"; public const string DhcpTtl = "dhcp-ttl"; + public const string TftpRoot = "tftp-root"; + public const string PxePrompt = "pxe-prompt"; + public const string EnableDbus = "enable-dbus"; + public const string EnableUbus = "enable-ubus"; + public const string FastDnsRetry = "fast-dns-retry"; /// Keys collected for effective config "server/local" multi-value (order preserved). public static readonly string[] ServerLocalKeys = { Server, Local }; diff --git a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqOptionTooltips.cs b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqOptionTooltips.cs index f0ed570..52e604c 100644 --- a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqOptionTooltips.cs +++ b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/DnsmasqOptionTooltips.cs @@ -16,6 +16,7 @@ public static class DnsmasqOptionTooltips // --- Hosts --- [DnsmasqConfKeys.NoHosts] = "Do not read /etc/hosts; only use addn-hosts and DHCP/hosts.", [DnsmasqConfKeys.AddnHosts] = "Additional hosts files (one per line).", + [DnsmasqConfKeys.Hostsdir] = "Directory of hosts files; new/changed files are read automatically.", // --- Resolver / DNS --- [DnsmasqConfKeys.ExpandHosts] = "Expand simple names in /etc/hosts with the local domain.", @@ -44,6 +45,7 @@ public static class DnsmasqOptionTooltips [DnsmasqConfKeys.FilterA] = "Remove A (IPv4) records from answers.", [DnsmasqConfKeys.FilterAaaa] = "Remove AAAA (IPv6) records from answers.", [DnsmasqConfKeys.LocaliseQueries] = "Return interface-specific answers from hosts/DHCP.", + [DnsmasqConfKeys.FastDnsRetry] = "DNS retry parameters: initial delay (ms) and optional continue time (ms).", [DnsmasqConfKeys.RebindDomainOk] = "Domains exempt from rebind checks. Can repeat.", [DnsmasqConfKeys.BogusNxdomain] = "Transform replies containing these IPs to NXDOMAIN. Can repeat.", [DnsmasqConfKeys.IgnoreAddress] = "Ignore A/AAAA replies containing these IPs. Can repeat.", @@ -55,6 +57,18 @@ public static class DnsmasqOptionTooltips [DnsmasqConfKeys.NoDhcpv4Interface] = "No DHCPv4 on these interfaces. Can repeat.", [DnsmasqConfKeys.NoDhcpv6Interface] = "No DHCPv6/RA on these interfaces. Can repeat.", + // --- DNS records --- + [DnsmasqConfKeys.Domain] = "Local domain(s); optional IP. Can repeat (e.g. domain=home,192.168.1.1).", + [DnsmasqConfKeys.Cname] = "CNAME records (alias, target). Can repeat.", + [DnsmasqConfKeys.MxHost] = "MX records (domain, host, priority). Can repeat.", + [DnsmasqConfKeys.Srv] = "SRV records. Can repeat.", + [DnsmasqConfKeys.PtrRecord] = "PTR records for reverse DNS. Can repeat.", + [DnsmasqConfKeys.TxtRecord] = "TXT records. Can repeat.", + [DnsmasqConfKeys.NaptrRecord] = "NAPTR records. Can repeat.", + [DnsmasqConfKeys.HostRecord] = "A/AAAA host records (name, IP). Can repeat.", + [DnsmasqConfKeys.DynamicHost] = "Dynamic host entries. Can repeat.", + [DnsmasqConfKeys.InterfaceName] = "Name per interface (for localise-queries). Can repeat.", + // --- DHCP --- [DnsmasqConfKeys.DhcpAuthoritative] = "DHCP server is authoritative; required for DHCP to work.", [DnsmasqConfKeys.LeasefileRo] = "Do not create or truncate the DHCP lease file.", @@ -64,6 +78,25 @@ public static class DnsmasqOptionTooltips [DnsmasqConfKeys.DhcpRange] = "DHCP address range(s) and lease time. Can repeat.", [DnsmasqConfKeys.DhcpHost] = "DHCP host entries (reservations by MAC or client-id). Can repeat.", [DnsmasqConfKeys.DhcpOption] = "DHCP option lines sent to clients. Can repeat.", + [DnsmasqConfKeys.DhcpMatch] = "Match DHCP clients (e.g. set tag from option). Can repeat.", + [DnsmasqConfKeys.DhcpBoot] = "Boot file and server for PXE. Can repeat.", + [DnsmasqConfKeys.DhcpIgnore] = "Ignore DHCP clients (e.g. by tag). Can repeat.", + [DnsmasqConfKeys.DhcpVendorclass] = "Match by DHCP vendor class. Can repeat.", + [DnsmasqConfKeys.DhcpUserclass] = "Match by DHCP user class. Can repeat.", + [DnsmasqConfKeys.RaParam] = "Router advertisement parameters (DHCPv6/RA). Can repeat.", + [DnsmasqConfKeys.Slaac] = "SLAAC host part for DHCPv6/RA. Can repeat.", + + // --- TFTP / PXE --- + [DnsmasqConfKeys.EnableTftp] = "Enable the built-in TFTP server.", + [DnsmasqConfKeys.TftpSecure] = "Only allow TFTP access from DHCP-assigned clients.", + [DnsmasqConfKeys.TftpRoot] = "Root directory for TFTP files.", + [DnsmasqConfKeys.PxePrompt] = "PXE boot prompt (e.g. timeout,0 to disable).", + [DnsmasqConfKeys.PxeService] = "PXE service definitions. Can repeat.", + + // --- DNSSEC --- + [DnsmasqConfKeys.Dnssec] = "Validate DNSSEC on replies from upstream.", + [DnsmasqConfKeys.DnssecCheckUnsigned] = "Treat unsigned zones as bogus.", + [DnsmasqConfKeys.TrustAnchor] = "DNSSEC trust anchors. Can repeat.", // --- Cache --- [DnsmasqConfKeys.CacheSize] = "Maximum number of DNS cache entries (0 to disable).", @@ -88,6 +121,8 @@ public static class DnsmasqOptionTooltips [DnsmasqConfKeys.LogAsync] = "Asynchronous logging; optional queue size.", [DnsmasqConfKeys.BindDynamic] = "Bind per-interface; auto-add new interfaces (Linux).", [DnsmasqConfKeys.LocalService] = "Restrict to local network or localhost (net|host).", + [DnsmasqConfKeys.EnableDbus] = "Enable DBus interface (optional service name).", + [DnsmasqConfKeys.EnableUbus] = "Enable UBus interface (optional service name).", }.ToFrozenDictionary(); /// Returns a short tooltip for the option, or null if none is defined. diff --git a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/EffectiveConfigFieldBuilder.cs b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/EffectiveConfigFieldBuilder.cs index f1bcae8..2a256d3 100644 --- a/src/DnsmasqWebUI/Infrastructure/Helpers/Config/EffectiveConfigFieldBuilder.cs +++ b/src/DnsmasqWebUI/Infrastructure/Helpers/Config/EffectiveConfigFieldBuilder.cs @@ -29,7 +29,10 @@ public static class EffectiveConfigFieldBuilder public const string SectionHosts = "hosts"; public const string SectionResolver = "resolver"; + public const string SectionDnsRecords = "dns-records"; public const string SectionDhcp = "dhcp"; + public const string SectionTftpPxe = "tftp-pxe"; + public const string SectionDnssec = "dnssec"; public const string SectionCache = "cache"; public const string SectionProcess = "process"; @@ -44,16 +47,19 @@ public static class EffectiveConfigFieldBuilder list.Add(Single(SectionHosts, DnsmasqConfKeys.NoHosts, status, s => Config(s)?.NoHosts, s => Sources(s)?.NoHosts, null)); list.Add(Multi(SectionHosts, DnsmasqConfKeys.AddnHosts, status, s => ToValueWithSourceList(s?.AddnHostsPaths, Sources(s)?.AddnHostsPaths))); + list.Add(Single(SectionHosts, DnsmasqConfKeys.Hostsdir, status, s => Config(s)?.HostsdirPath, s => Sources(s)?.HostsdirPath, null)); - // --- Resolver / DNS --- - list.Add(Single(SectionResolver, DnsmasqConfKeys.ExpandHosts, status, s => Config(s)?.ExpandHosts, s => Sources(s)?.ExpandHosts, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.BogusPriv, status, s => Config(s)?.BogusPriv, s => Sources(s)?.BogusPriv, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.StrictOrder, status, s => Config(s)?.StrictOrder, s => Sources(s)?.StrictOrder, null)); + // --- Resolver / DNS (most-used first: server/local, rev-server, address, resolv-file) --- + list.Add(Multi(SectionResolver, "server / local", status, Items(ec => ec?.ServerLocalValues, src => src?.ServerLocalValues))); + list.Add(Multi(SectionResolver, DnsmasqConfKeys.RevServer, status, Items(ec => ec?.RevServerValues, src => src?.RevServerValues))); + list.Add(Multi(SectionResolver, DnsmasqConfKeys.Address, status, Items(ec => ec?.AddressValues, src => src?.AddressValues))); + list.Add(Multi(SectionResolver, DnsmasqConfKeys.ResolvFile, status, Items(ec => ec?.ResolvFiles, src => src?.ResolvFiles))); list.Add(Single(SectionResolver, DnsmasqConfKeys.NoResolv, status, s => Config(s)?.NoResolv, s => Sources(s)?.NoResolv, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.DomainNeeded, status, s => Config(s)?.DomainNeeded, s => Sources(s)?.DomainNeeded, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.AllServers, status, s => Config(s)?.AllServers, s => Sources(s)?.AllServers, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.Port, status, s => Config(s)?.Port, s => Sources(s)?.Port, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.LogQueries, status, s => Config(s)?.LogQueries, s => Sources(s)?.LogQueries, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.StrictOrder, status, s => Config(s)?.StrictOrder, s => Sources(s)?.StrictOrder, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.AllServers, status, s => Config(s)?.AllServers, s => Sources(s)?.AllServers, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.AuthTtl, status, s => Config(s)?.AuthTtl, s => Sources(s)?.AuthTtl, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.EdnsPacketMax, status, s => Config(s)?.EdnsPacketMax, s => Sources(s)?.EdnsPacketMax, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.QueryPort, status, s => Config(s)?.QueryPort, s => Sources(s)?.QueryPort, null)); @@ -64,19 +70,30 @@ public static class EffectiveConfigFieldBuilder list.Add(Single(SectionResolver, DnsmasqConfKeys.StopDnsRebind, status, s => Config(s)?.StopDnsRebind, s => Sources(s)?.StopDnsRebind, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.RebindLocalhostOk, status, s => Config(s)?.RebindLocalhostOk, s => Sources(s)?.RebindLocalhostOk, null)); list.Add(Single(SectionResolver, DnsmasqConfKeys.ClearOnReload, status, s => Config(s)?.ClearOnReload, s => Sources(s)?.ClearOnReload, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.Filterwin2k, status, s => Config(s)?.Filterwin2k, s => Sources(s)?.Filterwin2k, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.FilterA, status, s => Config(s)?.FilterA, s => Sources(s)?.FilterA, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.FilterAaaa, status, s => Config(s)?.FilterAaaa, s => Sources(s)?.FilterAaaa, null)); - list.Add(Single(SectionResolver, DnsmasqConfKeys.LocaliseQueries, status, s => Config(s)?.LocaliseQueries, s => Sources(s)?.LocaliseQueries, null)); - list.Add(Multi(SectionResolver, "server / local", status, Items(ec => ec?.ServerLocalValues, src => src?.ServerLocalValues))); - list.Add(Multi(SectionResolver, DnsmasqConfKeys.RevServer, status, Items(ec => ec?.RevServerValues, src => src?.RevServerValues))); - list.Add(Multi(SectionResolver, DnsmasqConfKeys.Address, status, Items(ec => ec?.AddressValues, src => src?.AddressValues))); - list.Add(Multi(SectionResolver, DnsmasqConfKeys.ResolvFile, status, Items(ec => ec?.ResolvFiles, src => src?.ResolvFiles))); + list.Add(Single(SectionResolver, DnsmasqConfKeys.ExpandHosts, status, s => Config(s)?.ExpandHosts, s => Sources(s)?.ExpandHosts, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.BogusPriv, status, s => Config(s)?.BogusPriv, s => Sources(s)?.BogusPriv, null)); list.Add(Multi(SectionResolver, DnsmasqConfKeys.RebindDomainOk, status, Items(ec => ec?.RebindDomainOkValues, src => src?.RebindDomainOkValues))); list.Add(Multi(SectionResolver, DnsmasqConfKeys.BogusNxdomain, status, Items(ec => ec?.BogusNxdomainValues, src => src?.BogusNxdomainValues))); list.Add(Multi(SectionResolver, DnsmasqConfKeys.IgnoreAddress, status, Items(ec => ec?.IgnoreAddressValues, src => src?.IgnoreAddressValues))); list.Add(Multi(SectionResolver, DnsmasqConfKeys.Alias, status, Items(ec => ec?.AliasValues, src => src?.AliasValues))); list.Add(Multi(SectionResolver, DnsmasqConfKeys.FilterRr, status, Items(ec => ec?.FilterRrValues, src => src?.FilterRrValues))); + list.Add(Single(SectionResolver, DnsmasqConfKeys.Filterwin2k, status, s => Config(s)?.Filterwin2k, s => Sources(s)?.Filterwin2k, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.FilterA, status, s => Config(s)?.FilterA, s => Sources(s)?.FilterA, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.FilterAaaa, status, s => Config(s)?.FilterAaaa, s => Sources(s)?.FilterAaaa, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.LocaliseQueries, status, s => Config(s)?.LocaliseQueries, s => Sources(s)?.LocaliseQueries, null)); + list.Add(Single(SectionResolver, DnsmasqConfKeys.FastDnsRetry, status, s => Config(s)?.FastDnsRetry, s => Sources(s)?.FastDnsRetry, null)); + + // --- DNS records (authoritative / local) --- + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.Domain, status, Items(ec => ec?.DomainValues, src => src?.DomainValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.Cname, status, Items(ec => ec?.CnameValues, src => src?.CnameValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.MxHost, status, Items(ec => ec?.MxHostValues, src => src?.MxHostValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.Srv, status, Items(ec => ec?.SrvValues, src => src?.SrvValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.PtrRecord, status, Items(ec => ec?.PtrRecordValues, src => src?.PtrRecordValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.TxtRecord, status, Items(ec => ec?.TxtRecordValues, src => src?.TxtRecordValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.NaptrRecord, status, Items(ec => ec?.NaptrRecordValues, src => src?.NaptrRecordValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.HostRecord, status, Items(ec => ec?.HostRecordValues, src => src?.HostRecordValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.DynamicHost, status, Items(ec => ec?.DynamicHostValues, src => src?.DynamicHostValues))); + list.Add(Multi(SectionDnsRecords, DnsmasqConfKeys.InterfaceName, status, Items(ec => ec?.InterfaceNameValues, src => src?.InterfaceNameValues))); // --- DHCP --- list.Add(Single(SectionDhcp, DnsmasqConfKeys.DhcpAuthoritative, status, s => Config(s)?.DhcpAuthoritative, s => Sources(s)?.DhcpAuthoritative, null)); @@ -87,6 +104,25 @@ public static class EffectiveConfigFieldBuilder list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpRange, status, Items(ec => ec?.DhcpRanges, src => src?.DhcpRanges))); list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpHost, status, Items(ec => ec?.DhcpHostLines, src => src?.DhcpHostLines))); list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpOption, status, Items(ec => ec?.DhcpOptionLines, src => src?.DhcpOptionLines))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpMatch, status, Items(ec => ec?.DhcpMatchValues, src => src?.DhcpMatchValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpBoot, status, Items(ec => ec?.DhcpBootValues, src => src?.DhcpBootValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpIgnore, status, Items(ec => ec?.DhcpIgnoreValues, src => src?.DhcpIgnoreValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpVendorclass, status, Items(ec => ec?.DhcpVendorclassValues, src => src?.DhcpVendorclassValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.DhcpUserclass, status, Items(ec => ec?.DhcpUserclassValues, src => src?.DhcpUserclassValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.RaParam, status, Items(ec => ec?.RaParamValues, src => src?.RaParamValues))); + list.Add(Multi(SectionDhcp, DnsmasqConfKeys.Slaac, status, Items(ec => ec?.SlaacValues, src => src?.SlaacValues))); + + // --- TFTP / PXE --- + list.Add(Single(SectionTftpPxe, DnsmasqConfKeys.EnableTftp, status, s => Config(s)?.EnableTftp, s => Sources(s)?.EnableTftp, null)); + list.Add(Single(SectionTftpPxe, DnsmasqConfKeys.TftpSecure, status, s => Config(s)?.TftpSecure, s => Sources(s)?.TftpSecure, null)); + list.Add(Single(SectionTftpPxe, DnsmasqConfKeys.TftpRoot, status, s => Config(s)?.TftpRootPath, s => Sources(s)?.TftpRootPath, null)); + list.Add(Single(SectionTftpPxe, DnsmasqConfKeys.PxePrompt, status, s => Config(s)?.PxePrompt, s => Sources(s)?.PxePrompt, null)); + list.Add(Multi(SectionTftpPxe, DnsmasqConfKeys.PxeService, status, Items(ec => ec?.PxeServiceValues, src => src?.PxeServiceValues))); + + // --- DNSSEC --- + list.Add(Single(SectionDnssec, DnsmasqConfKeys.Dnssec, status, s => Config(s)?.Dnssec, s => Sources(s)?.Dnssec, null)); + list.Add(Single(SectionDnssec, DnsmasqConfKeys.DnssecCheckUnsigned, status, s => Config(s)?.DnssecCheckUnsigned, s => Sources(s)?.DnssecCheckUnsigned, null)); + list.Add(Multi(SectionDnssec, DnsmasqConfKeys.TrustAnchor, status, Items(ec => ec?.TrustAnchorValues, src => src?.TrustAnchorValues))); // --- Cache --- list.Add(Multi(SectionCache, DnsmasqConfKeys.CacheRr, status, Items(ec => ec?.CacheRrValues, src => src?.CacheRrValues))); @@ -116,6 +152,8 @@ public static class EffectiveConfigFieldBuilder list.Add(Single(SectionProcess, DnsmasqConfKeys.User, status, s => Config(s)?.User, s => Sources(s)?.User, null)); list.Add(Single(SectionProcess, DnsmasqConfKeys.Group, status, s => Config(s)?.Group, s => Sources(s)?.Group, null)); list.Add(Single(SectionProcess, DnsmasqConfKeys.LogFacility, status, s => Config(s)?.LogFacility, s => Sources(s)?.LogFacility, null)); + list.Add(Single(SectionProcess, DnsmasqConfKeys.EnableDbus, status, s => Config(s)?.EnableDbus, s => Sources(s)?.EnableDbus, null)); + list.Add(Single(SectionProcess, DnsmasqConfKeys.EnableUbus, status, s => Config(s)?.EnableUbus, s => Sources(s)?.EnableUbus, null)); return list; } diff --git a/src/DnsmasqWebUI/Infrastructure/Services/ConfigSetCache.cs b/src/DnsmasqWebUI/Infrastructure/Services/ConfigSetCache.cs index 59ff5d3..ee7a834 100644 --- a/src/DnsmasqWebUI/Infrastructure/Services/ConfigSetCache.cs +++ b/src/DnsmasqWebUI/Infrastructure/Services/ConfigSetCache.cs @@ -218,6 +218,8 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable { var noHosts = DnsmasqConfIncludeParser.GetNoHostsFromConfigFiles(paths, pathToLines); var addnHosts = DnsmasqConfIncludeParser.GetAddnHostsPathsFromConfigFiles(paths, pathToLines); + var (hostsdirVal, hostsdirDir) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Hostsdir); + var hostsdirPath = string.IsNullOrWhiteSpace(hostsdirVal) ? null : DnsmasqConfIncludeParser.ResolvePath(hostsdirVal?.Trim(), hostsdirDir); var serverLocal = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.ServerLocalKeys); var revServer = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.RevServer); var addressValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Address); @@ -227,6 +229,15 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var dhcpRanges = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpRange); var dhcpHostLines = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpHost); var dhcpOptionLines = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpOption); + var dhcpMatchValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpMatch); + var dhcpBootValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpBoot); + var dhcpIgnoreValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpIgnore); + var dhcpVendorclassValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpVendorclass); + var dhcpUserclassValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpUserclass); + var raParamValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.RaParam); + var slaacValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Slaac); + var pxeServiceValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.PxeService); + var trustAnchorValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.TrustAnchor); var resolvFiles = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.ResolvFile); var rebindDomainOk = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.RebindDomainOk); var bogusNxdomain = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.BogusNxdomain); @@ -238,6 +249,16 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var noDhcpInterface = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.NoDhcpInterface); var noDhcpv4Interface = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.NoDhcpv4Interface); var noDhcpv6Interface = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.NoDhcpv6Interface); + var domainValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Domain); + var cnameValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Cname); + var mxHostValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.MxHost); + var srvValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Srv); + var ptrRecordValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.PtrRecord); + var txtRecordValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.TxtRecord); + var naptrRecordValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.NaptrRecord); + var hostRecordValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.HostRecord); + var dynamicHostValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DynamicHost); + var interfaceNameValues = DnsmasqConfIncludeParser.GetMultiValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.InterfaceName); var expandHosts = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.ExpandHosts); var bogusPriv = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.BogusPriv); @@ -260,6 +281,10 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var logDebug = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.LogDebug); var dhcpAuthoritative = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpAuthoritative); var leasefileRo = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.LeasefileRo); + var enableTftp = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.EnableTftp); + var tftpSecure = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.TftpSecure); + var dnssec = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.Dnssec); + var dnssecCheckUnsigned = DnsmasqConfIncludeParser.GetFlagFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DnssecCheckUnsigned); var dhcpLeaseFilePath = DnsmasqConfIncludeParser.GetDhcpLeaseFilePathFromConfigFiles(paths, pathToLines); @@ -307,16 +332,29 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var minCacheTtl = TryParseInt(minCacheTtlVal); var (dhcpTtlVal, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.DhcpTtl); var dhcpTtl = TryParseInt(dhcpTtlVal); + var (tftpRootVal, tftpRootDir) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.TftpRoot); + var tftpRootPath = string.IsNullOrWhiteSpace(tftpRootVal) ? null : DnsmasqConfIncludeParser.ResolvePath(tftpRootVal?.Trim(), tftpRootDir); + var (pxePromptVal, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.PxePrompt); + var pxePrompt = string.IsNullOrWhiteSpace(pxePromptVal) ? null : pxePromptVal.Trim(); + var (enableDbusVal, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.EnableDbus); + var enableDbus = string.IsNullOrWhiteSpace(enableDbusVal) ? null : enableDbusVal.Trim(); + var (enableUbusVal, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.EnableUbus); + var enableUbus = string.IsNullOrWhiteSpace(enableUbusVal) ? null : enableUbusVal.Trim(); + var (fastDnsRetryVal, _) = DnsmasqConfIncludeParser.GetLastValueFromConfigFiles(paths, pathToLines, DnsmasqConfKeys.FastDnsRetry); + var fastDnsRetry = string.IsNullOrWhiteSpace(fastDnsRetryVal) ? null : fastDnsRetryVal.Trim(); return new EffectiveDnsmasqConfig( - noHosts, addnHosts, - serverLocal, revServer, addressValues, interfaces, listenAddresses, exceptInterfaces, dhcpRanges, dhcpHostLines, dhcpOptionLines, resolvFiles, + noHosts, addnHosts, hostsdirPath, + serverLocal, revServer, addressValues, interfaces, listenAddresses, exceptInterfaces, dhcpRanges, dhcpHostLines, dhcpOptionLines, + dhcpMatchValues, dhcpBootValues, dhcpIgnoreValues, dhcpVendorclassValues, dhcpUserclassValues, raParamValues, slaacValues, pxeServiceValues, trustAnchorValues, resolvFiles, rebindDomainOk, bogusNxdomain, ignoreAddress, alias, filterRr, cacheRr, authServer, noDhcpInterface, noDhcpv4Interface, noDhcpv6Interface, + domainValues, cnameValues, mxHostValues, srvValues, ptrRecordValues, txtRecordValues, naptrRecordValues, hostRecordValues, dynamicHostValues, interfaceNameValues, expandHosts, bogusPriv, strictOrder, allServers, noResolv, domainNeeded, noPoll, bindInterfaces, bindDynamic, noNegcache, dnsLoopDetect, stopDnsRebind, rebindLocalhostOk, clearOnReload, filterwin2k, filterA, filterAaaa, localiseQueries, logDebug, dhcpAuthoritative, leasefileRo, + enableTftp, tftpSecure, dnssec, dnssecCheckUnsigned, dhcpLeaseFilePath, cacheSize, port, localTtl, pidFilePath, user, group, logFacility, logQueries, authTtl, ednsPacketMax, queryPort, portLimit, minPort, maxPort, logAsync, localService, dhcpLeaseMax, - negTtl, maxTtl, maxCacheTtl, minCacheTtl, dhcpTtl + negTtl, maxTtl, maxCacheTtl, minCacheTtl, dhcpTtl, tftpRootPath, pxePrompt, enableDbus, enableUbus, fastDnsRetry ); } @@ -324,6 +362,7 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable { var (_, noHostsSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.NoHosts, managedFilePath); var addnHostsWithSource = DnsmasqConfIncludeParser.GetAddnHostsPathsFromConfigFilesWithSource(paths, pathToLines, managedFilePath); + var (_, hostsdirPathSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Hostsdir, managedFilePath); var serverLocalWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.ServerLocalKeys, managedFilePath); var revServerWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.RevServer, managedFilePath); var addressWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Address, managedFilePath); @@ -333,6 +372,15 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var dhcpRangesWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpRange, managedFilePath); var dhcpHostLinesWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpHost, managedFilePath); var dhcpOptionLinesWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpOption, managedFilePath); + var dhcpMatchWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpMatch, managedFilePath); + var dhcpBootWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpBoot, managedFilePath); + var dhcpIgnoreWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpIgnore, managedFilePath); + var dhcpVendorclassWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpVendorclass, managedFilePath); + var dhcpUserclassWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpUserclass, managedFilePath); + var raParamWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.RaParam, managedFilePath); + var slaacWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Slaac, managedFilePath); + var pxeServiceWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.PxeService, managedFilePath); + var trustAnchorWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.TrustAnchor, managedFilePath); var resolvFilesWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.ResolvFile, managedFilePath); var rebindDomainOkWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.RebindDomainOk, managedFilePath); var bogusNxdomainWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.BogusNxdomain, managedFilePath); @@ -344,6 +392,16 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var noDhcpInterfaceWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.NoDhcpInterface, managedFilePath); var noDhcpv4InterfaceWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.NoDhcpv4Interface, managedFilePath); var noDhcpv6InterfaceWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.NoDhcpv6Interface, managedFilePath); + var domainWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Domain, managedFilePath); + var cnameWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Cname, managedFilePath); + var mxHostWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.MxHost, managedFilePath); + var srvWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Srv, managedFilePath); + var ptrRecordWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.PtrRecord, managedFilePath); + var txtRecordWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.TxtRecord, managedFilePath); + var naptrRecordWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.NaptrRecord, managedFilePath); + var hostRecordWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.HostRecord, managedFilePath); + var dynamicHostWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DynamicHost, managedFilePath); + var interfaceNameWithSource = DnsmasqConfIncludeParser.GetMultiValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.InterfaceName, managedFilePath); var (_, expandHostsSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.ExpandHosts, managedFilePath); var (_, bogusPrivSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.BogusPriv, managedFilePath); @@ -366,6 +424,10 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var (_, logDebugSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.LogDebug, managedFilePath); var (_, dhcpAuthoritativeSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpAuthoritative, managedFilePath); var (_, leasefileRoSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.LeasefileRo, managedFilePath); + var (_, enableTftpSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.EnableTftp, managedFilePath); + var (_, tftpSecureSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.TftpSecure, managedFilePath); + var (_, dnssecSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.Dnssec, managedFilePath); + var (_, dnssecCheckUnsignedSource) = DnsmasqConfIncludeParser.GetFlagFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DnssecCheckUnsigned, managedFilePath); var (_, dhcpLeaseFilePathSource) = DnsmasqConfIncludeParser.GetDhcpLeaseFilePathFromConfigFilesWithSource(paths, pathToLines, managedFilePath); var (_, cacheSizeSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.CacheSize, managedFilePath); @@ -390,9 +452,14 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable var (_, maxCacheTtlSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.MaxCacheTtl, managedFilePath); var (_, minCacheTtlSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.MinCacheTtl, managedFilePath); var (_, dhcpTtlSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.DhcpTtl, managedFilePath); + var (_, tftpRootPathSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.TftpRoot, managedFilePath); + var (_, pxePromptSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.PxePrompt, managedFilePath); + var (_, enableDbusSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.EnableDbus, managedFilePath); + var (_, enableUbusSource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.EnableUbus, managedFilePath); + var (_, fastDnsRetrySource) = DnsmasqConfIncludeParser.GetLastValueFromConfigFilesWithSource(paths, pathToLines, DnsmasqConfKeys.FastDnsRetry, managedFilePath); return new EffectiveConfigSources( - noHostsSource, addnHostsWithSource.Select(t => new PathWithSource(t.Path, t.Source)).ToList(), + noHostsSource, addnHostsWithSource.Select(t => new PathWithSource(t.Path, t.Source)).ToList(), hostsdirPathSource, serverLocalWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), revServerWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), addressWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), @@ -402,6 +469,15 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable dhcpRangesWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), dhcpHostLinesWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), dhcpOptionLinesWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dhcpMatchWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dhcpBootWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dhcpIgnoreWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dhcpVendorclassWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dhcpUserclassWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + raParamWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + slaacWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + pxeServiceWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + trustAnchorWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), resolvFilesWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), rebindDomainOkWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), bogusNxdomainWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), @@ -413,12 +489,69 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable noDhcpInterfaceWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), noDhcpv4InterfaceWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), noDhcpv6InterfaceWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), - expandHostsSource, bogusPrivSource, strictOrderSource, allServersSource, noResolvSource, domainNeededSource, noPollSource, - bindInterfacesSource, bindDynamicSource, noNegcacheSource, dnsLoopDetectSource, stopDnsRebindSource, rebindLocalhostOkSource, clearOnReloadSource, - filterwin2kSource, filterASource, filterAaaaSource, localiseQueriesSource, logDebugSource, dhcpAuthoritativeSource, leasefileRoSource, - dhcpLeaseFilePathSource, cacheSizeSource, portSource, localTtlSource, pidFilePathSource, userSource, groupSource, - logFacilitySource, logQueriesSource, authTtlSource, ednsPacketMaxSource, queryPortSource, portLimitSource, minPortSource, maxPortSource, logAsyncSource, localServiceSource, - dhcpLeaseMaxSource, negTtlSource, maxTtlSource, maxCacheTtlSource, minCacheTtlSource, dhcpTtlSource + domainWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + cnameWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + mxHostWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + srvWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + ptrRecordWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + txtRecordWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + naptrRecordWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + hostRecordWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + dynamicHostWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + interfaceNameWithSource.Select(t => new ValueWithSource(t.Value, t.Source)).ToList(), + expandHostsSource, + bogusPrivSource, + strictOrderSource, + allServersSource, + noResolvSource, + domainNeededSource, + noPollSource, + bindInterfacesSource, + bindDynamicSource, + noNegcacheSource, + dnsLoopDetectSource, + stopDnsRebindSource, + rebindLocalhostOkSource, + clearOnReloadSource, + filterwin2kSource, + filterASource, + filterAaaaSource, + localiseQueriesSource, + logDebugSource, + dhcpAuthoritativeSource, + leasefileRoSource, + enableTftpSource, + tftpSecureSource, + dnssecSource, + dnssecCheckUnsignedSource, + dhcpLeaseFilePathSource, + cacheSizeSource, + portSource, + localTtlSource, + pidFilePathSource, + userSource, + groupSource, + logFacilitySource, + logQueriesSource, + authTtlSource, + ednsPacketMaxSource, + queryPortSource, + portLimitSource, + minPortSource, + maxPortSource, + logAsyncSource, + localServiceSource, + dhcpLeaseMaxSource, + negTtlSource, + maxTtlSource, + maxCacheTtlSource, + minCacheTtlSource, + dhcpTtlSource, + tftpRootPathSource, + pxePromptSource, + enableDbusSource, + enableUbusSource, + fastDnsRetrySource ); } @@ -456,38 +589,56 @@ public sealed class ConfigSetCache : IConfigSetCache, IDisposable private static EffectiveDnsmasqConfig CreateDefaultEffectiveConfig() => new( - NoHosts: false, AddnHostsPaths: Array.Empty(), + NoHosts: false, AddnHostsPaths: Array.Empty(), HostsdirPath: null, ServerLocalValues: Array.Empty(), RevServerValues: Array.Empty(), AddressValues: Array.Empty(), Interfaces: Array.Empty(), ListenAddresses: Array.Empty(), ExceptInterfaces: Array.Empty(), DhcpRanges: Array.Empty(), - DhcpHostLines: Array.Empty(), DhcpOptionLines: Array.Empty(), ResolvFiles: Array.Empty(), - RebindDomainOkValues: Array.Empty(), BogusNxdomainValues: Array.Empty(), IgnoreAddressValues: Array.Empty(), + DhcpHostLines: Array.Empty(), DhcpOptionLines: Array.Empty(), + DhcpMatchValues: Array.Empty(), DhcpBootValues: Array.Empty(), DhcpIgnoreValues: Array.Empty(), + DhcpVendorclassValues: Array.Empty(), DhcpUserclassValues: Array.Empty(), + RaParamValues: Array.Empty(), SlaacValues: Array.Empty(), PxeServiceValues: Array.Empty(), TrustAnchorValues: Array.Empty(), + ResolvFiles: Array.Empty(), RebindDomainOkValues: Array.Empty(), BogusNxdomainValues: Array.Empty(), IgnoreAddressValues: Array.Empty(), AliasValues: Array.Empty(), FilterRrValues: Array.Empty(), CacheRrValues: Array.Empty(), - AuthServerValues: Array.Empty(), NoDhcpInterfaceValues: Array.Empty(), NoDhcpv4InterfaceValues: Array.Empty(), NoDhcpv6InterfaceValues: Array.Empty(), + AuthServerValues: Array.Empty(), NoDhcpInterfaceValues: Array.Empty(), NoDhcpv4InterfaceValues: Array.Empty(), NoDhcpv6InterfaceValues: Array.Empty(), + DomainValues: Array.Empty(), CnameValues: Array.Empty(), MxHostValues: Array.Empty(), SrvValues: Array.Empty(), + PtrRecordValues: Array.Empty(), TxtRecordValues: Array.Empty(), NaptrRecordValues: Array.Empty(), + HostRecordValues: Array.Empty(), DynamicHostValues: Array.Empty(), InterfaceNameValues: Array.Empty(), ExpandHosts: false, BogusPriv: false, StrictOrder: false, AllServers: false, NoResolv: false, DomainNeeded: false, NoPoll: false, BindInterfaces: false, BindDynamic: false, NoNegcache: false, DnsLoopDetect: false, StopDnsRebind: false, RebindLocalhostOk: false, ClearOnReload: false, Filterwin2k: false, FilterA: false, FilterAaaa: false, LocaliseQueries: false, LogDebug: false, DhcpAuthoritative: false, LeasefileRo: false, + EnableTftp: false, TftpSecure: false, Dnssec: false, DnssecCheckUnsigned: false, DhcpLeaseFilePath: null, CacheSize: null, Port: null, LocalTtl: null, PidFilePath: null, User: null, Group: null, LogFacility: null, LogQueries: null, AuthTtl: null, EdnsPacketMax: null, QueryPort: null, PortLimit: null, MinPort: null, MaxPort: null, LogAsync: null, LocalService: null, - DhcpLeaseMax: null, NegTtl: null, MaxTtl: null, MaxCacheTtl: null, MinCacheTtl: null, DhcpTtl: null + DhcpLeaseMax: null, NegTtl: null, MaxTtl: null, MaxCacheTtl: null, MinCacheTtl: null, DhcpTtl: null, + TftpRootPath: null, PxePrompt: null, EnableDbus: null, EnableUbus: null, FastDnsRetry: null ); private static EffectiveConfigSources CreateDefaultEffectiveConfigSources() => new( - NoHosts: null, AddnHostsPaths: Array.Empty(), + NoHosts: null, AddnHostsPaths: Array.Empty(), HostsdirPath: null, ServerLocalValues: Array.Empty(), RevServerValues: Array.Empty(), AddressValues: Array.Empty(), Interfaces: Array.Empty(), ListenAddresses: Array.Empty(), ExceptInterfaces: Array.Empty(), DhcpRanges: Array.Empty(), - DhcpHostLines: Array.Empty(), DhcpOptionLines: Array.Empty(), + DhcpHostLines: Array.Empty(), + DhcpOptionLines: Array.Empty(), + DhcpMatchValues: Array.Empty(), DhcpBootValues: Array.Empty(), DhcpIgnoreValues: Array.Empty(), + DhcpVendorclassValues: Array.Empty(), DhcpUserclassValues: Array.Empty(), + RaParamValues: Array.Empty(), SlaacValues: Array.Empty(), PxeServiceValues: Array.Empty(), TrustAnchorValues: Array.Empty(), ResolvFiles: Array.Empty(), RebindDomainOkValues: Array.Empty(), BogusNxdomainValues: Array.Empty(), IgnoreAddressValues: Array.Empty(), AliasValues: Array.Empty(), FilterRrValues: Array.Empty(), CacheRrValues: Array.Empty(), - AuthServerValues: Array.Empty(), NoDhcpInterfaceValues: Array.Empty(), NoDhcpv4InterfaceValues: Array.Empty(), NoDhcpv6InterfaceValues: Array.Empty(), + AuthServerValues: Array.Empty(), NoDhcpInterfaceValues: Array.Empty(), NoDhcpv4InterfaceValues: Array.Empty(), + NoDhcpv6InterfaceValues: Array.Empty(), + DomainValues: Array.Empty(), CnameValues: Array.Empty(), MxHostValues: Array.Empty(), SrvValues: Array.Empty(), + PtrRecordValues: Array.Empty(), TxtRecordValues: Array.Empty(), NaptrRecordValues: Array.Empty(), + HostRecordValues: Array.Empty(), DynamicHostValues: Array.Empty(), InterfaceNameValues: Array.Empty(), ExpandHosts: null, BogusPriv: null, StrictOrder: null, AllServers: null, NoResolv: null, DomainNeeded: null, NoPoll: null, BindInterfaces: null, BindDynamic: null, NoNegcache: null, DnsLoopDetect: null, StopDnsRebind: null, RebindLocalhostOk: null, ClearOnReload: null, Filterwin2k: null, FilterA: null, FilterAaaa: null, LocaliseQueries: null, LogDebug: null, DhcpAuthoritative: null, LeasefileRo: null, + EnableTftp: null, TftpSecure: null, Dnssec: null, DnssecCheckUnsigned: null, DhcpLeaseFilePath: null, CacheSize: null, Port: null, LocalTtl: null, PidFilePath: null, User: null, Group: null, LogFacility: null, LogQueries: null, AuthTtl: null, EdnsPacketMax: null, QueryPort: null, PortLimit: null, MinPort: null, MaxPort: null, LogAsync: null, LocalService: null, - DhcpLeaseMax: null, NegTtl: null, MaxTtl: null, MaxCacheTtl: null, MinCacheTtl: null, DhcpTtl: null + DhcpLeaseMax: null, NegTtl: null, MaxTtl: null, MaxCacheTtl: null, MinCacheTtl: null, DhcpTtl: null, + TftpRootPath: null, PxePrompt: null, EnableDbus: null, EnableUbus: null, FastDnsRetry: null ); private static int? TryParseInt(string? value) diff --git a/src/DnsmasqWebUI/Infrastructure/Services/EffectiveConfigRenderFragmentRegistry.cs b/src/DnsmasqWebUI/Infrastructure/Services/EffectiveConfigRenderFragmentRegistry.cs index 0480900..7efc82f 100644 --- a/src/DnsmasqWebUI/Infrastructure/Services/EffectiveConfigRenderFragmentRegistry.cs +++ b/src/DnsmasqWebUI/Infrastructure/Services/EffectiveConfigRenderFragmentRegistry.cs @@ -43,6 +43,10 @@ public class EffectiveConfigRenderFragmentRegistry : IEffectiveConfigRenderFragm RegisterFlag(EffectiveConfigFieldBuilder.SectionResolver, DnsmasqConfKeys.LocaliseQueries); RegisterFlag(EffectiveConfigFieldBuilder.SectionDhcp, DnsmasqConfKeys.DhcpAuthoritative); RegisterFlag(EffectiveConfigFieldBuilder.SectionDhcp, DnsmasqConfKeys.LeasefileRo); + RegisterFlag(EffectiveConfigFieldBuilder.SectionTftpPxe, DnsmasqConfKeys.EnableTftp); + RegisterFlag(EffectiveConfigFieldBuilder.SectionTftpPxe, DnsmasqConfKeys.TftpSecure); + RegisterFlag(EffectiveConfigFieldBuilder.SectionDnssec, DnsmasqConfKeys.Dnssec); + RegisterFlag(EffectiveConfigFieldBuilder.SectionDnssec, DnsmasqConfKeys.DnssecCheckUnsigned); } private void RegisterFlag(string sectionId, string optionName) diff --git a/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveConfigSources.cs b/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveConfigSources.cs index 572d768..69507ac 100644 --- a/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveConfigSources.cs +++ b/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveConfigSources.cs @@ -13,6 +13,7 @@ public record EffectiveConfigSources( // --- Hosts --- ConfigValueSource? NoHosts, IReadOnlyList AddnHostsPaths, + ConfigValueSource? HostsdirPath, // --- Multi-value (ARG_DUP): source per value --- IReadOnlyList ServerLocalValues, @@ -24,6 +25,15 @@ public record EffectiveConfigSources( IReadOnlyList DhcpRanges, IReadOnlyList DhcpHostLines, IReadOnlyList DhcpOptionLines, + IReadOnlyList DhcpMatchValues, + IReadOnlyList DhcpBootValues, + IReadOnlyList DhcpIgnoreValues, + IReadOnlyList DhcpVendorclassValues, + IReadOnlyList DhcpUserclassValues, + IReadOnlyList RaParamValues, + IReadOnlyList SlaacValues, + IReadOnlyList PxeServiceValues, + IReadOnlyList TrustAnchorValues, IReadOnlyList ResolvFiles, IReadOnlyList RebindDomainOkValues, IReadOnlyList BogusNxdomainValues, @@ -35,6 +45,16 @@ public record EffectiveConfigSources( IReadOnlyList NoDhcpInterfaceValues, IReadOnlyList NoDhcpv4InterfaceValues, IReadOnlyList NoDhcpv6InterfaceValues, + IReadOnlyList DomainValues, + IReadOnlyList CnameValues, + IReadOnlyList MxHostValues, + IReadOnlyList SrvValues, + IReadOnlyList PtrRecordValues, + IReadOnlyList TxtRecordValues, + IReadOnlyList NaptrRecordValues, + IReadOnlyList HostRecordValues, + IReadOnlyList DynamicHostValues, + IReadOnlyList InterfaceNameValues, // --- Flags (set if any occurrence; source = first file that set it, so we know if readonly) --- ConfigValueSource? ExpandHosts, @@ -58,6 +78,10 @@ public record EffectiveConfigSources( ConfigValueSource? LogDebug, ConfigValueSource? DhcpAuthoritative, ConfigValueSource? LeasefileRo, + ConfigValueSource? EnableTftp, + ConfigValueSource? TftpSecure, + ConfigValueSource? Dnssec, + ConfigValueSource? DnssecCheckUnsigned, // --- Single-value (last occurrence wins; source = file that set the last value) --- ConfigValueSource? DhcpLeaseFilePath, @@ -82,5 +106,10 @@ public record EffectiveConfigSources( ConfigValueSource? MaxTtl, ConfigValueSource? MaxCacheTtl, ConfigValueSource? MinCacheTtl, - ConfigValueSource? DhcpTtl + ConfigValueSource? DhcpTtl, + ConfigValueSource? TftpRootPath, + ConfigValueSource? PxePrompt, + ConfigValueSource? EnableDbus, + ConfigValueSource? EnableUbus, + ConfigValueSource? FastDnsRetry ); diff --git a/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveDnsmasqConfig.cs b/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveDnsmasqConfig.cs index cbbd0ce..f57c9ee 100644 --- a/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveDnsmasqConfig.cs +++ b/src/DnsmasqWebUI/Models/Dnsmasq/EffectiveConfig/EffectiveDnsmasqConfig.cs @@ -17,6 +17,7 @@ public record EffectiveDnsmasqConfig( // --- Hosts (already used by Hosts UI) --- bool NoHosts, IReadOnlyList AddnHostsPaths, + string? HostsdirPath, // --- Multi-value (ARG_DUP): all occurrences in order --- IReadOnlyList ServerLocalValues, @@ -28,6 +29,15 @@ public record EffectiveDnsmasqConfig( IReadOnlyList DhcpRanges, IReadOnlyList DhcpHostLines, IReadOnlyList DhcpOptionLines, + IReadOnlyList DhcpMatchValues, + IReadOnlyList DhcpBootValues, + IReadOnlyList DhcpIgnoreValues, + IReadOnlyList DhcpVendorclassValues, + IReadOnlyList DhcpUserclassValues, + IReadOnlyList RaParamValues, + IReadOnlyList SlaacValues, + IReadOnlyList PxeServiceValues, + IReadOnlyList TrustAnchorValues, IReadOnlyList ResolvFiles, IReadOnlyList RebindDomainOkValues, IReadOnlyList BogusNxdomainValues, @@ -39,6 +49,16 @@ public record EffectiveDnsmasqConfig( IReadOnlyList NoDhcpInterfaceValues, IReadOnlyList NoDhcpv4InterfaceValues, IReadOnlyList NoDhcpv6InterfaceValues, + IReadOnlyList DomainValues, + IReadOnlyList CnameValues, + IReadOnlyList MxHostValues, + IReadOnlyList SrvValues, + IReadOnlyList PtrRecordValues, + IReadOnlyList TxtRecordValues, + IReadOnlyList NaptrRecordValues, + IReadOnlyList HostRecordValues, + IReadOnlyList DynamicHostValues, + IReadOnlyList InterfaceNameValues, // --- Boolean flags (set if any file contains the option) --- bool ExpandHosts, @@ -62,6 +82,10 @@ public record EffectiveDnsmasqConfig( bool LogDebug, bool DhcpAuthoritative, bool LeasefileRo, + bool EnableTftp, + bool TftpSecure, + bool Dnssec, + bool DnssecCheckUnsigned, // --- Single-value options (last occurrence wins; null = not set, dnsmasq default) --- string? DhcpLeaseFilePath, @@ -86,7 +110,12 @@ public record EffectiveDnsmasqConfig( int? MaxTtl, int? MaxCacheTtl, int? MinCacheTtl, - int? DhcpTtl + int? DhcpTtl, + string? TftpRootPath, + string? PxePrompt, + string? EnableDbus, + string? EnableUbus, + string? FastDnsRetry ) { ///