using System.Collections.Generic; namespace DnsmasqWebUI.Infrastructure.Helpers.Config; /// /// Whether an effective-config option has a single value (or flag) or multiple values. /// Single source of truth for descriptor building and UI; flags are treated as single-value. /// public enum EffectiveConfigFieldKind { Single, Multi, } /// /// How to parse an option from config files: last occurrence wins, key-only flag, or collect all values. /// Used by ConfigSetCache to choose GetLastValue / GetFlag / GetMultiValue without hard-coding per option. /// public enum EffectiveConfigParserBehavior { LastWins, Flag, Multi, } /// /// Maps dnsmasq option names to single vs multi-value kind. Used by the field builder so call sites /// do not choose AddSingleDescriptor vs AddMultiDescriptor explicitly. /// public static class EffectiveConfigOptionKindMap { private static readonly IReadOnlyDictionary KindByOptionName = new Dictionary(System.StringComparer.Ordinal) { [DnsmasqConfKeys.NoHosts] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AddnHosts] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Hostsdir] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ReadEthers] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Server] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Local] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.RevServer] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Address] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.ResolvFile] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.NoResolv] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DomainNeeded] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Port] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LogQueries] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.StrictOrder] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AllServers] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AuthTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.EdnsPacketMax] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.QueryPort] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.PortLimit] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.MinPort] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.MaxPort] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnsLoopDetect] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.StopDnsRebind] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.RebindLocalhostOk] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ClearOnReload] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ExpandHosts] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.BogusPriv] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.RebindDomainOk] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.BogusNxdomain] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.IgnoreAddress] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Alias] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.FilterRr] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Filterwin2k] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.FilterA] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.FilterAaaa] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LocaliseQueries] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.FastDnsRetry] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Ipset] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Nftset] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Domain] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Cname] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.MxHost] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Srv] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.PtrRecord] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.TxtRecord] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.NaptrRecord] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.HostRecord] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DynamicHost] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.InterfaceName] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.MxTarget] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Localmx] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Selfmx] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpAuthoritative] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpRapidCommit] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LeasefileRo] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpScript] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpLeasefile] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpLeaseMax] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpRange] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpHost] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpOption] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpOptionForce] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpMatch] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpMac] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpNameMatch] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpIgnoreNames] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpHostsfile] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpOptsfile] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpHostsdir] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpBoot] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpIgnore] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpVendorclass] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpUserclass] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.RaParam] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Slaac] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.EnableTftp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.TftpSecure] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.TftpNoFail] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.TftpNoBlocksize] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.TftpRoot] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.PxePrompt] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.PxeService] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.Dnssec] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnssecCheckUnsigned] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ProxyDnssec] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.TrustAnchor] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.CacheRr] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.CacheSize] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LocalTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NoNegcache] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NegTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.MaxTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.MaxCacheTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.MinCacheTtl] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NoPoll] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.BindInterfaces] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.BindDynamic] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LogDebug] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LogAsync] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LocalService] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Interface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.ListenAddress] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.ExceptInterface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.AuthServer] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.NoDhcpInterface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.NoDhcpv4Interface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.NoDhcpv6Interface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.PidFile] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.User] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Group] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LogFacility] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.EnableDbus] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.EnableUbus] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.EnableRa] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.LogDhcp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.KeepInForeground] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NoDaemon] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Conntrack] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ConnmarkAllowlistEnable] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NoRoundRobin] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnssecNoTimecheck] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnssecDebug] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Leasequery] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpGenerateNames] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpBroadcast] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpSequentialIp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpIgnoreClid] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.BootpDynamic] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.NoPing] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ScriptArp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ScriptOnRenewal] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpNoOverride] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.QuietDhcp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.QuietDhcp6] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.QuietRa] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.QuietTftp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnsForwardMax] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Dumpfile] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Dumpmask] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AddCpeId] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnssecTimestamp] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DnssecLimits] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpAlternatePort] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpDuid] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpLuascript] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpScriptuser] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.DhcpPxeVendor] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.ConnmarkAllowlist] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.CaaRecord] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DnsRr] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.SynthDomain] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.AuthZone] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.AuthSoa] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.AuthSecServers] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.AuthPeer] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpRelay] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpCircuitid] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpRemoteid] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpSubscrid] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpProxy] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.TagIf] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.BridgeInterface] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.SharedNetwork] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.DhcpOptionPxe] = EffectiveConfigFieldKind.Multi, [DnsmasqConfKeys.UseStaleCache] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AddMac] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.AddSubnet] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Umbrella] = EffectiveConfigFieldKind.Single, [DnsmasqConfKeys.Do0x20Encode] = EffectiveConfigFieldKind.Single, }; /// Returns Single or Multi for the given option name; defaults to Single if unknown. public static EffectiveConfigFieldKind GetKind(string optionName) => KindByOptionName.TryGetValue(optionName, out var kind) ? kind : EffectiveConfigFieldKind.Single; } /// /// Maps dnsmasq option names to parser behavior (LastWins / Flag / Multi). Used by ConfigSetCache so it /// dispatches to GetLastValue, GetFlag, or GetMultiValue from one place. Special cases (NoHosts value, /// AddnHosts, DhcpLeaseFilePath) remain explicit in the cache. /// public static class EffectiveConfigParserBehaviorMap { private static readonly IReadOnlyDictionary BehaviorByOptionName = new Dictionary(System.StringComparer.Ordinal) { [DnsmasqConfKeys.NoHosts] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.AddnHosts] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Hostsdir] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.ReadEthers] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.Server] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Local] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.RevServer] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Address] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.ResolvFile] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.NoResolv] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DomainNeeded] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.Port] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.LogQueries] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.StrictOrder] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.AllServers] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.AuthTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.EdnsPacketMax] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.QueryPort] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.PortLimit] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.MinPort] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.MaxPort] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DnsLoopDetect] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.StopDnsRebind] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.RebindLocalhostOk] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ClearOnReload] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ExpandHosts] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.BogusPriv] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.RebindDomainOk] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.BogusNxdomain] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.IgnoreAddress] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Alias] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.FilterRr] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Filterwin2k] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.FilterA] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.FilterAaaa] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.LocaliseQueries] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.FastDnsRetry] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Ipset] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Nftset] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Domain] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Cname] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.MxHost] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Srv] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.PtrRecord] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.TxtRecord] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.NaptrRecord] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.HostRecord] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DynamicHost] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.InterfaceName] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.MxTarget] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Localmx] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.Selfmx] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpAuthoritative] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpRapidCommit] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.LeasefileRo] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpScript] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpLeasefile] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpLeaseMax] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpRange] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpHost] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpOption] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpOptionForce] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpMatch] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpMac] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpNameMatch] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpIgnoreNames] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpHostsfile] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpOptsfile] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpHostsdir] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpBoot] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpIgnore] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpVendorclass] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpUserclass] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.RaParam] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Slaac] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.EnableTftp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.TftpSecure] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.TftpNoFail] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.TftpNoBlocksize] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.TftpRoot] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.PxePrompt] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.PxeService] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.Dnssec] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DnssecCheckUnsigned] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ProxyDnssec] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.TrustAnchor] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.CacheRr] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.CacheSize] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.LocalTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.NoNegcache] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.NegTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.MaxTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.MaxCacheTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.MinCacheTtl] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.NoPoll] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.BindInterfaces] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.BindDynamic] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.LogDebug] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.LogAsync] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.LocalService] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Interface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.ListenAddress] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.ExceptInterface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.AuthServer] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.NoDhcpInterface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.NoDhcpv4Interface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.NoDhcpv6Interface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.PidFile] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.User] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Group] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.LogFacility] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.EnableDbus] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.EnableUbus] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.EnableRa] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.LogDhcp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.KeepInForeground] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.NoDaemon] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.Conntrack] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ConnmarkAllowlistEnable] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.NoRoundRobin] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DnssecNoTimecheck] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DnssecDebug] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.Leasequery] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpGenerateNames] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpBroadcast] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpSequentialIp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpIgnoreClid] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.BootpDynamic] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.NoPing] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ScriptArp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.ScriptOnRenewal] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DhcpNoOverride] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.QuietDhcp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.QuietDhcp6] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.QuietRa] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.QuietTftp] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.DnsForwardMax] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Dumpfile] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Dumpmask] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.AddCpeId] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DnssecTimestamp] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DnssecLimits] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpAlternatePort] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpDuid] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpLuascript] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpScriptuser] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.DhcpPxeVendor] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.ConnmarkAllowlist] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.CaaRecord] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DnsRr] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.SynthDomain] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.AuthZone] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.AuthSoa] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.AuthSecServers] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.AuthPeer] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpRelay] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpCircuitid] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpRemoteid] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpSubscrid] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpProxy] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.TagIf] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.BridgeInterface] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.SharedNetwork] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.DhcpOptionPxe] = EffectiveConfigParserBehavior.Multi, [DnsmasqConfKeys.UseStaleCache] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.AddMac] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.AddSubnet] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Umbrella] = EffectiveConfigParserBehavior.LastWins, [DnsmasqConfKeys.Do0x20Encode] = EffectiveConfigParserBehavior.Flag, [DnsmasqConfKeys.No0x20Encode] = EffectiveConfigParserBehavior.Flag, }; /// Returns LastWins, Flag, or Multi for the given option name; defaults to LastWins if unknown. public static EffectiveConfigParserBehavior GetBehavior(string optionName) => BehaviorByOptionName.TryGetValue(optionName, out var b) ? b : EffectiveConfigParserBehavior.LastWins; } /// /// How to serialize an option when writing the managed config file. /// Used by DnsmasqConfigService so KeyOnlyOrValue and InversePair options serialize correctly. /// public enum EffectiveConfigWriteBehavior { Flag, SingleValue, MultiValue, KeyOnlyOrValue, InversePair, } /// /// Maps dnsmasq option names to write behavior. Options not in the map default to SingleValue /// (or are inferred from parser behavior in the service). Add entries for KeyOnlyOrValue and InversePair options. /// public static class EffectiveConfigWriteBehaviorMap { private static readonly IReadOnlyDictionary BehaviorByOptionName = new Dictionary(StringComparer.Ordinal) { [DnsmasqConfKeys.Conntrack] = EffectiveConfigWriteBehavior.Flag, [DnsmasqConfKeys.UseStaleCache] = EffectiveConfigWriteBehavior.KeyOnlyOrValue, [DnsmasqConfKeys.AddMac] = EffectiveConfigWriteBehavior.KeyOnlyOrValue, [DnsmasqConfKeys.AddSubnet] = EffectiveConfigWriteBehavior.KeyOnlyOrValue, [DnsmasqConfKeys.Umbrella] = EffectiveConfigWriteBehavior.KeyOnlyOrValue, [DnsmasqConfKeys.Do0x20Encode] = EffectiveConfigWriteBehavior.InversePair, }; /// For InversePair options: (key for "enabled", key for "disabled"). Null if not an InversePair or unknown. private static readonly IReadOnlyDictionary InversePairKeysByOptionName = new Dictionary(StringComparer.Ordinal) { [DnsmasqConfKeys.Do0x20Encode] = (DnsmasqConfKeys.Do0x20Encode, DnsmasqConfKeys.No0x20Encode), }; /// Returns write behavior for the option; defaults to SingleValue if unknown. public static EffectiveConfigWriteBehavior GetBehavior(string optionName) => BehaviorByOptionName.TryGetValue(optionName, out var b) ? b : EffectiveConfigWriteBehavior.SingleValue; /// Returns the pair of config keys (enabled, disabled) for an InversePair option; null otherwise. public static (string KeyA, string KeyB)? GetInversePairKeys(string optionName) => InversePairKeysByOptionName.TryGetValue(optionName, out var pair) ? pair : null; }