diff options
Diffstat (limited to 'internal/config')
| -rw-r--r-- | internal/config/config.go | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/internal/config/config.go b/internal/config/config.go new file mode 100644 index 0000000..f2624c2 --- /dev/null +++ b/internal/config/config.go @@ -0,0 +1,152 @@ +package config + +import ( + "flag" + "fmt" + + "github.com/BurntSushi/toml" +) + +type Config struct { + Server ServerConfig `toml:"server"` + Cache CacheConfig `toml:"cache"` + Resolver ResolverConfig `toml:"resolver"` + Blocklist BlocklistConfig `toml:"blocklist"` + Log LogConfig `toml:"log"` +} + +type ServerConfig struct { + ListenUDP string `toml:"listen_udp"` + ListenTCP string `toml:"listen_tcp"` + ListenDOH string `toml:"listen_doh"` +} + +type CacheConfig struct { + MaxEntries int `toml:"max_entries"` + DBPath string `toml:"db_path"` +} + +type ResolverConfig struct { + Timeout string `toml:"timeout"` + MaxDelegations int `toml:"max_delegations"` +} + +type BlocklistConfig struct { + Response string `toml:"response"` + Files []string `toml:"files"` + URLs []string `toml:"urls"` +} + +type LogConfig struct { + Level string `toml:"level"` +} + +type CLIFlags struct { + Config string + LogLevel string + ListenUDP string + ListenTCP string + ListenDOH string +} + +func ParseFlags() CLIFlags { + var f CLIFlags + flag.StringVar(&f.Config, "config", "linum.toml", "path to config file") + flag.StringVar(&f.LogLevel, "loglevel", "", "log level (debug|info|warn|error)") + flag.StringVar(&f.ListenUDP, "udp", "", "UDP listen address") + flag.StringVar(&f.ListenTCP, "tcp", "", "TCP listen address") + flag.StringVar(&f.ListenDOH, "doh", "", "DoH listen address") + flag.Parse() + return f +} + +func Default() Config{ + return Config{ + Server: ServerConfig{ + ListenUDP: ":5353", + ListenTCP: ":5353", + ListenDOH: ":8443", + }, + Cache: CacheConfig{ + MaxEntries: 100000, + }, + Resolver: ResolverConfig{ + Timeout: "2s", + MaxDelegations: 30, + }, + Blocklist: BlocklistConfig{ + Response: "zero_ip", + }, + Log: LogConfig{ + Level: "info", + }, + } +} + +func LoadFile(path string) (Config, error) { + var cfg Config + _, err := toml.DecodeFile(path, &cfg) + return cfg, err +} + +func Merge(dst, src Config) Config { + if src.Server.ListenUDP != "" { + dst.Server.ListenUDP = src.Server.ListenUDP + } + if src.Server.ListenTCP != "" { + dst.Server.ListenTCP = src.Server.ListenTCP + } + if src.Server.ListenDOH != "" { + dst.Server.ListenDOH = src.Server.ListenDOH + } + if src.Cache.MaxEntries > 0 { + dst.Cache.MaxEntries = src.Cache.MaxEntries + } + if src.Cache.DBPath != "" { + dst.Cache.DBPath = src.Cache.DBPath + } + if src.Resolver.Timeout != "" { + dst.Resolver.Timeout = src.Resolver.Timeout + } + if src.Resolver.MaxDelegations > 0 { + dst.Resolver.MaxDelegations = src.Resolver.MaxDelegations + } + if src.Blocklist.Response != "" { + dst.Blocklist.Response = src.Blocklist.Response + } + if len(src.Blocklist.Files) > 0 { + dst.Blocklist.Files = src.Blocklist.Files + } + if len(src.Blocklist.URLs) > 0 { + dst.Blocklist.URLs = src.Blocklist.URLs + } + if src.Log.Level != "" { + dst.Log.Level = src.Log.Level + } + return dst +} + +func (f CLIFlags) Apply(cfg Config) Config { + if f.ListenUDP != "" { + cfg.Server.ListenUDP = f.ListenUDP + } + if f.ListenTCP != "" { + cfg.Server.ListenTCP = f.ListenTCP + } + if f.ListenDOH != "" { + cfg.Server.ListenDOH = f.ListenDOH + } + if f.LogLevel != "" { + cfg.Log.Level = f.LogLevel + } + return cfg +} + +func (c Config) Validate() error { + switch c.Blocklist.Response { + case "zero_ip", "nxdomain", "": + default: + return fmt.Errorf("invalid blocklist response %q (want zero_ip or nxdomain)", c.Blocklist.Response) + } + return nil +} |
