Files
styx/dataset/parser/dns.go
2025-10-06 22:25:23 +02:00

140 lines
3.3 KiB
Go

package parser
import (
"bufio"
"io"
"strings"
"github.com/miekg/dns"
)
func init() {
RegisterDomainsParser(dnsmasqDomainsParser{})
RegisterDomainsParser(mosDNSDomainsParser{})
RegisterDomainsParser(smartDNSDomainsParser{})
RegisterDomainsParser(unboundDomainsParser{})
}
type dnsmasqDomainsParser struct{}
func (dnsmasqDomainsParser) CanHandle(line string) bool {
return strings.HasPrefix(line, "address=/")
}
func (dnsmasqDomainsParser) ParseDomains(r io.Reader) (domains []string, ignored int, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if isComment(line) {
continue
}
switch {
case strings.HasPrefix(line, "address=/"):
part := strings.FieldsFunc(line, func(r rune) bool { return r == '/' })
if len(part) >= 3 && isDomainName(part[1]) {
domains = append(domains, part[1])
continue
}
}
ignored++
}
if err = scanner.Err(); err != nil {
return
}
return unique(domains), ignored, nil
}
type mosDNSDomainsParser struct{}
func (mosDNSDomainsParser) CanHandle(line string) bool {
if strings.HasPrefix(line, "domain:") {
return isDomainName(line[7:])
}
return false
}
func (mosDNSDomainsParser) ParseDomains(r io.Reader) (domains []string, ignored int, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if isComment(line) {
continue
}
if strings.HasPrefix(line, "domain:") {
domains = append(domains, line[7:])
continue
}
ignored++
}
if err = scanner.Err(); err != nil {
return
}
return unique(domains), ignored, nil
}
type smartDNSDomainsParser struct{}
func (smartDNSDomainsParser) CanHandle(line string) bool {
return strings.HasPrefix(line, "address /")
}
func (smartDNSDomainsParser) ParseDomains(r io.Reader) (domains []string, ignored int, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if isComment(line) {
continue
}
if strings.HasPrefix(line, "address /") {
if i := strings.IndexByte(line[9:], '/'); i > -1 {
domains = append(domains, line[9:i+9])
continue
}
}
ignored++
}
if err = scanner.Err(); err != nil {
return
}
return unique(domains), ignored, nil
}
type unboundDomainsParser struct{}
func (unboundDomainsParser) CanHandle(line string) bool {
return strings.HasPrefix(line, "local-data:") ||
strings.HasPrefix(line, "local-zone:")
}
func (unboundDomainsParser) ParseDomains(r io.Reader) (domains []string, ignored int, err error) {
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if isComment(line) {
continue
}
switch {
case strings.HasPrefix(line, "local-data:"):
record := strings.Trim(strings.TrimSpace(line[11:]), `"`)
if rr, err := dns.NewRR(record); err == nil {
switch rr.Header().Rrtype {
case dns.TypeA, dns.TypeAAAA, dns.TypeCNAME:
domains = append(domains, strings.Trim(rr.Header().Name, `.`))
continue
}
}
case strings.HasPrefix(line, "local-zone:") && strings.HasSuffix(line, " reject"):
line = strings.Trim(strings.TrimSpace(line[11:]), `"`)
if i := strings.IndexByte(line, '"'); i > -1 {
domains = append(domains, line[:i])
continue
}
}
ignored++
}
if err = scanner.Err(); err != nil {
return
}
return unique(domains), ignored, nil
}