Effective config: option kind map, parser behavior map, custom displays

- Add EffectiveConfigOptionKindMap (Single/Multi kind + LastWins/Flag/Multi parser
  behavior) and drive field builder + ConfigSetCache from it.
- Single AddDescriptor() in list extensions that dispatches via kind map to
  AddSingleDescriptor/AddMultiDescriptor.
- ConfigSetCache: ParseOptionValue/ParseOptionWithSource dispatch by option
  name; BuildEffectiveConfig and BuildEffectiveConfigSources use them with
  casts; special cases (NoHosts, AddnHosts, server/local, DhcpLeaseFilePath)
  remain explicit.
- Add IntegerValueDisplay, LogQueriesDisplay, LocalServiceDisplay; register
  integers with bounds/units in EffectiveConfigRenderFragmentRegistry.
- Add EffectiveConfigDescriptorFactory, EffectiveIntegerConfigFieldDescriptor,
  IEffectiveConfigFieldDescriptor for integer descriptor metadata.
This commit is contained in:
2026-02-14 00:18:28 +10:00
parent ecd9e5cc7b
commit 906e222ec1
16 changed files with 999 additions and 368 deletions
@@ -0,0 +1,292 @@
using System.Collections.Generic;
namespace DnsmasqWebUI.Infrastructure.Helpers.Config;
/// <summary>
/// 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.
/// </summary>
public enum EffectiveConfigFieldKind
{
Single,
Multi,
}
/// <summary>
/// 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.
/// </summary>
public enum EffectiveConfigParserBehavior
{
LastWins,
Flag,
Multi,
}
/// <summary>
/// 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.
/// </summary>
public static class EffectiveConfigOptionKindMap
{
private static readonly IReadOnlyDictionary<string, EffectiveConfigFieldKind> KindByOptionName =
new Dictionary<string, EffectiveConfigFieldKind>(System.StringComparer.Ordinal)
{
[DnsmasqConfKeys.NoHosts] = EffectiveConfigFieldKind.Single,
[DnsmasqConfKeys.AddnHosts] = EffectiveConfigFieldKind.Multi,
[DnsmasqConfKeys.Hostsdir] = EffectiveConfigFieldKind.Single,
[DnsmasqConfKeys.ReadEthers] = EffectiveConfigFieldKind.Single,
[DnsmasqOptionTooltips.ServerLocalLabel] = 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,
};
/// <summary>Returns Single or Multi for the given option name; defaults to Single if unknown.</summary>
public static EffectiveConfigFieldKind GetKind(string optionName) =>
KindByOptionName.TryGetValue(optionName, out var kind) ? kind : EffectiveConfigFieldKind.Single;
}
/// <summary>
/// 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, server/local keys array, DhcpLeaseFilePath) remain explicit in the cache.
/// </summary>
public static class EffectiveConfigParserBehaviorMap
{
private static readonly IReadOnlyDictionary<string, EffectiveConfigParserBehavior> BehaviorByOptionName =
new Dictionary<string, EffectiveConfigParserBehavior>(System.StringComparer.Ordinal)
{
[DnsmasqConfKeys.NoHosts] = EffectiveConfigParserBehavior.Flag,
[DnsmasqConfKeys.AddnHosts] = EffectiveConfigParserBehavior.Multi,
[DnsmasqConfKeys.Hostsdir] = EffectiveConfigParserBehavior.LastWins,
[DnsmasqConfKeys.ReadEthers] = EffectiveConfigParserBehavior.Flag,
[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.LastWins,
};
/// <summary>Returns LastWins, Flag, or Multi for the given option name; defaults to LastWins if unknown.</summary>
public static EffectiveConfigParserBehavior GetBehavior(string optionName) =>
BehaviorByOptionName.TryGetValue(optionName, out var b) ? b : EffectiveConfigParserBehavior.LastWins;
}