diff --git a/dnscrypt-proxy/config.go b/dnscrypt-proxy/config.go index 2f825ae9..4573c0eb 100644 --- a/dnscrypt-proxy/config.go +++ b/dnscrypt-proxy/config.go @@ -1,6 +1,7 @@ package main import ( + "encoding/json" "errors" "flag" "fmt" @@ -104,11 +105,21 @@ type BlockIPConfig struct { Format string `toml:"log_format"` } +type ServerSummary struct { + Name string `json:"name"` + Proto string `json:"proto"` + DNSSEC bool `json:"dnssec"` + NoLog bool `json:"nolog"` + NoFilter bool `json:"nofilter"` + Description string `json:"description,omitempty"` +} + func ConfigLoad(proxy *Proxy, svcFlag *string) error { version := flag.Bool("version", false, "Prints current proxy version") configFile := flag.String("config", DefaultConfigFileName, "Path to the configuration file") resolve := flag.String("resolve", "", "resolve a name using system libraries") list := flag.Bool("list", false, "print the list of available resolvers for the enabled filters") + jsonOutput := flag.Bool("json", false, "output list as JSON") flag.Parse() if *svcFlag == "stop" || *svcFlag == "uninstall" { return nil @@ -217,14 +228,38 @@ func ConfigLoad(proxy *Proxy, svcFlag *string) error { return errors.New("No servers configured") } if *list { - for _, registeredServer := range proxy.registeredServers { - fmt.Println(registeredServer.name) - } + config.printRegisteredServers(proxy, *jsonOutput) os.Exit(0) } return nil } +func (config *Config) printRegisteredServers(proxy *Proxy, jsonOutput bool) { + var summary []ServerSummary + for _, registeredServer := range proxy.registeredServers { + serverSummary := ServerSummary{ + Name: registeredServer.name, + Proto: registeredServer.stamp.proto.String(), + DNSSEC: registeredServer.stamp.props&ServerInformalPropertyDNSSEC != 0, + NoLog: registeredServer.stamp.props&ServerInformalPropertyNoLog != 0, + NoFilter: registeredServer.stamp.props&ServerInformalPropertyNoFilter != 0, + Description: registeredServer.description, + } + if jsonOutput { + summary = append(summary, serverSummary) + } else { + fmt.Println(serverSummary.Name) + } + } + if jsonOutput { + jsonStr, err := json.MarshalIndent(summary, "", " ") + if err != nil { + dlog.Fatal(err) + } + fmt.Print(string(jsonStr)) + } +} + func (config *Config) loadSources(proxy *Proxy) error { requiredProps := ServerInformalProperties(0) if config.SourceRequireDNSSEC { @@ -296,7 +331,7 @@ func (config *Config) loadSource(proxy *Proxy, requiredProps ServerInformalPrope continue } } else if registeredServer.stamp.props&requiredProps != requiredProps { - return nil + continue } if config.SourceIPv4 || config.SourceIPv6 { isIPv4, isIPv6 := true, false diff --git a/dnscrypt-proxy/serversInfo.go b/dnscrypt-proxy/serversInfo.go index 915ead6e..fe3bbf2a 100644 --- a/dnscrypt-proxy/serversInfo.go +++ b/dnscrypt-proxy/serversInfo.go @@ -32,8 +32,9 @@ const ( ) type RegisteredServer struct { - name string - stamp ServerStamp + name string + stamp ServerStamp + description string } type ServerInfo struct { diff --git a/dnscrypt-proxy/sources.go b/dnscrypt-proxy/sources.go index d4e7983c..8a010300 100644 --- a/dnscrypt-proxy/sources.go +++ b/dnscrypt-proxy/sources.go @@ -235,14 +235,24 @@ func (source *Source) parseV2(prefix string) ([]RegisteredServer, error) { if len(name) == 0 { return registeredServers, fmt.Errorf("Invalid format for source at [%s]", source.url) } + subparts = subparts[1:] name = prefix + name - var stampStr string + var stampStr, description string for _, subpart := range subparts { subpart = strings.TrimFunc(subpart, unicode.IsSpace) if strings.HasPrefix(subpart, "sdns://") { + if len(stampStr) > 0 { + return registeredServers, fmt.Errorf("Multiple stamps for server [%s] in source from [%s]", name, source.url) + } stampStr = subpart - break + continue + } else if len(subpart) == 0 || strings.HasPrefix(subpart, "//") { + continue } + if len(description) > 0 { + description += "\n" + } + description += subpart } if len(stampStr) < 8 { return registeredServers, fmt.Errorf("Missing stamp for server [%s] in source from [%s]", name, source.url) @@ -252,7 +262,7 @@ func (source *Source) parseV2(prefix string) ([]RegisteredServer, error) { return registeredServers, err } registeredServer := RegisteredServer{ - name: name, stamp: stamp, + name: name, stamp: stamp, description: description, } dlog.Debugf("Registered [%s] with stamp [%s]", name, stamp.String()) registeredServers = append(registeredServers, registeredServer) diff --git a/dnscrypt-proxy/stamps.go b/dnscrypt-proxy/stamps.go index b33aacda..775b33de 100644 --- a/dnscrypt-proxy/stamps.go +++ b/dnscrypt-proxy/stamps.go @@ -21,6 +21,19 @@ const ( StampProtoTypeDoH = StampProtoType(0x02) ) +func (stampProtoType *StampProtoType) String() string { + switch *stampProtoType { + case StampProtoTypePlain: + return "Plain" + case StampProtoTypeDNSCrypt: + return "DNSCrypt" + case StampProtoTypeDoH: + return "DoH" + default: + panic("Unexpected protocol") + } +} + type ServerStamp struct { serverAddrStr string serverPk []uint8