mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-04 04:18:13 +10:00
Infrastructure: - Parsers under Serialization/Parsers: Dnsmasq, DnsmasqConfig, EffectiveConfig - EffectiveConfig: Abstractions, Metadata (keys, views, field builder, tooltips, placeholders, write semantics), Rendering, Editing, Validation/Handlers, Readonly - Helpers/Config: only DnsmasqFileEncoding; DnsmasqOptionTooltips moved to Metadata - Remove empty Infrastructure/Parsers and Helpers/Dnsmasq Tests: - Mirror main project: Serialization/Parsers (Dnsmasq, DnsmasqConfig), Services/Dnsmasq/Config, Services/EffectiveConfig, Models, Helpers (TestDataHelper) - Namespaces updated; usings for TestDataHelper and Metadata where needed Docs: README codebase overview and test layout updated.
250 lines
10 KiB
C#
250 lines
10 KiB
C#
using System.Collections.Frozen;
|
|
|
|
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Metadata;
|
|
|
|
/// <summary>
|
|
/// Single source of truth: which effective-config sections exist, their display order and titles,
|
|
/// and which option (conf key) belongs to which section. Used by the field builder (section lookup)
|
|
/// and by the UI (section order, context filtering).
|
|
/// </summary>
|
|
public static class EffectiveConfigSections
|
|
{
|
|
// --- Section IDs (used by registry, views, etc.) ---
|
|
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";
|
|
|
|
/// <summary>Section definition: id, display title, option names in display order.</summary>
|
|
public sealed record SectionDef(string SectionId, string Title, string[] OptionNames);
|
|
|
|
/// <summary>All sections in display order with their option names. Defines option → section mapping.</summary>
|
|
public static readonly IReadOnlyList<SectionDef> Sections =
|
|
[
|
|
new SectionDef(SectionHosts, "Hosts", [
|
|
DnsmasqConfKeys.NoHosts,
|
|
DnsmasqConfKeys.AddnHosts,
|
|
DnsmasqConfKeys.Hostsdir,
|
|
DnsmasqConfKeys.ReadEthers,
|
|
]),
|
|
new SectionDef(SectionResolver, "Resolver / DNS", [
|
|
DnsmasqConfKeys.Server,
|
|
DnsmasqConfKeys.Local,
|
|
DnsmasqConfKeys.RevServer,
|
|
DnsmasqConfKeys.Address,
|
|
DnsmasqConfKeys.ResolvFile,
|
|
DnsmasqConfKeys.NoResolv,
|
|
DnsmasqConfKeys.DomainNeeded,
|
|
DnsmasqConfKeys.Port,
|
|
DnsmasqConfKeys.LogQueries,
|
|
DnsmasqConfKeys.StrictOrder,
|
|
DnsmasqConfKeys.AllServers,
|
|
DnsmasqConfKeys.AuthTtl,
|
|
DnsmasqConfKeys.EdnsPacketMax,
|
|
DnsmasqConfKeys.QueryPort,
|
|
DnsmasqConfKeys.PortLimit,
|
|
DnsmasqConfKeys.MinPort,
|
|
DnsmasqConfKeys.MaxPort,
|
|
DnsmasqConfKeys.DnsLoopDetect,
|
|
DnsmasqConfKeys.StopDnsRebind,
|
|
DnsmasqConfKeys.RebindLocalhostOk,
|
|
DnsmasqConfKeys.ClearOnReload,
|
|
DnsmasqConfKeys.ExpandHosts,
|
|
DnsmasqConfKeys.BogusPriv,
|
|
DnsmasqConfKeys.RebindDomainOk,
|
|
DnsmasqConfKeys.BogusNxdomain,
|
|
DnsmasqConfKeys.IgnoreAddress,
|
|
DnsmasqConfKeys.Alias,
|
|
DnsmasqConfKeys.FilterRr,
|
|
DnsmasqConfKeys.Filterwin2k,
|
|
DnsmasqConfKeys.FilterA,
|
|
DnsmasqConfKeys.FilterAaaa,
|
|
DnsmasqConfKeys.LocaliseQueries,
|
|
DnsmasqConfKeys.FastDnsRetry,
|
|
DnsmasqConfKeys.Ipset,
|
|
DnsmasqConfKeys.Nftset,
|
|
DnsmasqConfKeys.ConnmarkAllowlistEnable,
|
|
DnsmasqConfKeys.NoRoundRobin,
|
|
DnsmasqConfKeys.DnsForwardMax,
|
|
DnsmasqConfKeys.ConnmarkAllowlist,
|
|
DnsmasqConfKeys.Do0x20Encode,
|
|
]),
|
|
new SectionDef(SectionDnsRecords, "DNS records", [
|
|
DnsmasqConfKeys.Domain,
|
|
DnsmasqConfKeys.Cname,
|
|
DnsmasqConfKeys.MxHost,
|
|
DnsmasqConfKeys.Srv,
|
|
DnsmasqConfKeys.PtrRecord,
|
|
DnsmasqConfKeys.TxtRecord,
|
|
DnsmasqConfKeys.NaptrRecord,
|
|
DnsmasqConfKeys.HostRecord,
|
|
DnsmasqConfKeys.DynamicHost,
|
|
DnsmasqConfKeys.InterfaceName,
|
|
DnsmasqConfKeys.CaaRecord,
|
|
DnsmasqConfKeys.DnsRr,
|
|
DnsmasqConfKeys.SynthDomain,
|
|
DnsmasqConfKeys.AuthZone,
|
|
DnsmasqConfKeys.AuthSoa,
|
|
DnsmasqConfKeys.AuthSecServers,
|
|
DnsmasqConfKeys.AuthPeer,
|
|
DnsmasqConfKeys.MxTarget,
|
|
DnsmasqConfKeys.Localmx,
|
|
DnsmasqConfKeys.Selfmx,
|
|
]),
|
|
new SectionDef(SectionDhcp, "DHCP", [
|
|
DnsmasqConfKeys.DhcpAuthoritative,
|
|
DnsmasqConfKeys.DhcpRapidCommit,
|
|
DnsmasqConfKeys.LeasefileRo,
|
|
DnsmasqConfKeys.Leasequery,
|
|
DnsmasqConfKeys.DhcpGenerateNames,
|
|
DnsmasqConfKeys.DhcpBroadcast,
|
|
DnsmasqConfKeys.DhcpSequentialIp,
|
|
DnsmasqConfKeys.DhcpIgnoreClid,
|
|
DnsmasqConfKeys.BootpDynamic,
|
|
DnsmasqConfKeys.NoPing,
|
|
DnsmasqConfKeys.ScriptArp,
|
|
DnsmasqConfKeys.ScriptOnRenewal,
|
|
DnsmasqConfKeys.DhcpNoOverride,
|
|
DnsmasqConfKeys.DhcpScript,
|
|
DnsmasqConfKeys.DhcpAlternatePort,
|
|
DnsmasqConfKeys.DhcpDuid,
|
|
DnsmasqConfKeys.DhcpLuascript,
|
|
DnsmasqConfKeys.DhcpScriptuser,
|
|
DnsmasqConfKeys.DhcpLeasefile,
|
|
DnsmasqConfKeys.DhcpLeaseMax,
|
|
DnsmasqConfKeys.DhcpTtl,
|
|
DnsmasqConfKeys.DhcpRange,
|
|
DnsmasqConfKeys.DhcpHost,
|
|
DnsmasqConfKeys.DhcpOption,
|
|
DnsmasqConfKeys.DhcpOptionForce,
|
|
DnsmasqConfKeys.DhcpMatch,
|
|
DnsmasqConfKeys.DhcpMac,
|
|
DnsmasqConfKeys.DhcpNameMatch,
|
|
DnsmasqConfKeys.DhcpIgnoreNames,
|
|
DnsmasqConfKeys.DhcpHostsfile,
|
|
DnsmasqConfKeys.DhcpOptsfile,
|
|
DnsmasqConfKeys.DhcpHostsdir,
|
|
DnsmasqConfKeys.DhcpOptsdir,
|
|
DnsmasqConfKeys.DhcpBoot,
|
|
DnsmasqConfKeys.DhcpIgnore,
|
|
DnsmasqConfKeys.DhcpVendorclass,
|
|
DnsmasqConfKeys.DhcpUserclass,
|
|
DnsmasqConfKeys.DhcpRelay,
|
|
DnsmasqConfKeys.DhcpCircuitid,
|
|
DnsmasqConfKeys.DhcpRemoteid,
|
|
DnsmasqConfKeys.DhcpSubscrid,
|
|
DnsmasqConfKeys.DhcpProxy,
|
|
DnsmasqConfKeys.TagIf,
|
|
DnsmasqConfKeys.BridgeInterface,
|
|
DnsmasqConfKeys.SharedNetwork,
|
|
DnsmasqConfKeys.RaParam,
|
|
DnsmasqConfKeys.Slaac,
|
|
]),
|
|
new SectionDef(SectionTftpPxe, "TFTP / PXE", [
|
|
DnsmasqConfKeys.EnableTftp,
|
|
DnsmasqConfKeys.TftpSecure,
|
|
DnsmasqConfKeys.TftpNoFail,
|
|
DnsmasqConfKeys.TftpNoBlocksize,
|
|
DnsmasqConfKeys.TftpRoot,
|
|
DnsmasqConfKeys.PxePrompt,
|
|
DnsmasqConfKeys.PxeService,
|
|
DnsmasqConfKeys.DhcpPxeVendor,
|
|
DnsmasqConfKeys.DhcpOptionPxe,
|
|
]),
|
|
new SectionDef(SectionDnssec, "DNSSEC", [
|
|
DnsmasqConfKeys.Dnssec,
|
|
DnsmasqConfKeys.DnssecCheckUnsigned,
|
|
DnsmasqConfKeys.DnssecNoTimecheck,
|
|
DnsmasqConfKeys.DnssecDebug,
|
|
DnsmasqConfKeys.ProxyDnssec,
|
|
DnsmasqConfKeys.AddCpeId,
|
|
DnsmasqConfKeys.DnssecTimestamp,
|
|
DnsmasqConfKeys.DnssecLimits,
|
|
DnsmasqConfKeys.TrustAnchor,
|
|
]),
|
|
new SectionDef(SectionCache, "Cache", [
|
|
DnsmasqConfKeys.CacheRr,
|
|
DnsmasqConfKeys.CacheSize,
|
|
DnsmasqConfKeys.LocalTtl,
|
|
DnsmasqConfKeys.NoNegcache,
|
|
DnsmasqConfKeys.NegTtl,
|
|
DnsmasqConfKeys.MaxTtl,
|
|
DnsmasqConfKeys.MaxCacheTtl,
|
|
DnsmasqConfKeys.MinCacheTtl,
|
|
DnsmasqConfKeys.Dumpfile,
|
|
DnsmasqConfKeys.Dumpmask,
|
|
DnsmasqConfKeys.UseStaleCache,
|
|
DnsmasqConfKeys.AddMac,
|
|
DnsmasqConfKeys.StripMac,
|
|
DnsmasqConfKeys.AddSubnet,
|
|
DnsmasqConfKeys.StripSubnet,
|
|
DnsmasqConfKeys.Umbrella,
|
|
]),
|
|
new SectionDef(SectionProcess, "Process & networking", [
|
|
DnsmasqConfKeys.NoPoll,
|
|
DnsmasqConfKeys.BindInterfaces,
|
|
DnsmasqConfKeys.BindDynamic,
|
|
DnsmasqConfKeys.LogDebug,
|
|
DnsmasqConfKeys.LogAsync,
|
|
DnsmasqConfKeys.LocalService,
|
|
DnsmasqConfKeys.Interface,
|
|
DnsmasqConfKeys.ListenAddress,
|
|
DnsmasqConfKeys.ExceptInterface,
|
|
DnsmasqConfKeys.AuthServer,
|
|
DnsmasqConfKeys.NoDhcpInterface,
|
|
DnsmasqConfKeys.NoDhcpv4Interface,
|
|
DnsmasqConfKeys.NoDhcpv6Interface,
|
|
DnsmasqConfKeys.PidFile,
|
|
DnsmasqConfKeys.User,
|
|
DnsmasqConfKeys.Group,
|
|
DnsmasqConfKeys.LogFacility,
|
|
DnsmasqConfKeys.EnableDbus,
|
|
DnsmasqConfKeys.EnableUbus,
|
|
DnsmasqConfKeys.EnableRa,
|
|
DnsmasqConfKeys.LogDhcp,
|
|
DnsmasqConfKeys.KeepInForeground,
|
|
DnsmasqConfKeys.NoDaemon,
|
|
DnsmasqConfKeys.Conntrack,
|
|
DnsmasqConfKeys.QuietDhcp,
|
|
DnsmasqConfKeys.QuietDhcp6,
|
|
DnsmasqConfKeys.QuietRa,
|
|
DnsmasqConfKeys.QuietTftp,
|
|
]),
|
|
];
|
|
|
|
private static FrozenDictionary<string, string>? _optionToSection;
|
|
|
|
/// <summary>Maps option name (conf key or display label) to section id. Used by Single/Multi in the builder.</summary>
|
|
public static string GetSectionId(string optionName)
|
|
{
|
|
_optionToSection ??= BuildOptionToSection();
|
|
return _optionToSection.TryGetValue(optionName, out var sectionId) ? sectionId : SectionResolver;
|
|
}
|
|
|
|
/// <summary>Section id and title in display order. Use for rendering section headers.</summary>
|
|
public static IReadOnlyList<(string SectionId, string Title)> GetSectionsInOrder() =>
|
|
Sections.Select(s => (s.SectionId, s.Title)).ToList();
|
|
|
|
/// <summary>Option names in the given section (display order). For context/views that restrict by section.</summary>
|
|
public static IReadOnlyList<string> GetOptionsInSection(string sectionId)
|
|
{
|
|
var def = Sections.FirstOrDefault(s => string.Equals(s.SectionId, sectionId, StringComparison.OrdinalIgnoreCase));
|
|
return def?.OptionNames ?? Array.Empty<string>();
|
|
}
|
|
|
|
private static FrozenDictionary<string, string> BuildOptionToSection()
|
|
{
|
|
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
|
foreach (var section in Sections)
|
|
{
|
|
foreach (var option in section.OptionNames)
|
|
dict[option] = section.SectionId;
|
|
}
|
|
return dict.ToFrozenDictionary(StringComparer.OrdinalIgnoreCase);
|
|
}
|
|
}
|