Changes to allow host "Set" to be standard, providers being able to use other query types, cache all responses, etc.

This commit is contained in:
Tyler
2020-02-07 22:38:22 -05:00
parent f726a5d5ae
commit 3383c5e4f9
10 changed files with 107 additions and 172 deletions

View File

@ -1,22 +1,15 @@
package hosts
import (
"net"
"time"
)
const (
notIPQuery = 0
_IP4Query = 4
_IP6Query = 6
)
var (
zeroDuration = time.Duration(0)
)
type Hosts interface {
Get(domain string, family int) ([]net.IP, time.Duration, bool)
Get(queryType uint16, domain string) ([]string, time.Duration, bool)
}
type ProviderList struct {
@ -24,7 +17,8 @@ type ProviderList struct {
}
type Provider interface {
Get(domain string) ([]string, time.Duration, bool)
Get(queryType uint16, domain string) ([]string, time.Duration, bool)
Set(t, domain, value string) (bool, error)
}
func NewHosts(providers []Provider) Hosts {
@ -34,38 +28,22 @@ func NewHosts(providers []Provider) Hosts {
/*
Match local /etc/hosts file first, remote redis records second
*/
func (h *ProviderList) Get(domain string, family int) ([]net.IP, time.Duration, bool) {
var sips []string
func (h *ProviderList) Get(queryType uint16, domain string) ([]string, time.Duration, bool) {
var vals []string
var ok bool
var ip net.IP
var ips []net.IP
var ttl time.Duration
for _, provider := range h.providers {
sips, ttl, ok = provider.Get(domain)
vals, ttl, ok = provider.Get(queryType, domain)
if ok {
break
}
}
if sips == nil {
if vals == nil {
return nil, zeroDuration, false
}
for _, sip := range sips {
switch family {
case _IP4Query:
ip = net.ParseIP(sip).To4()
case _IP6Query:
ip = net.ParseIP(sip).To16()
default:
continue
}
if ip != nil {
ips = append(ips, ip)
}
}
return ips, ttl, ips != nil
return vals, ttl, true
}

View File

@ -2,7 +2,9 @@ package hosts
import (
"bufio"
"errors"
"github.com/fsnotify/fsnotify"
"github.com/miekg/dns"
"github.com/ryanuber/go-glob"
"meow.tf/joker/godns/log"
"meow.tf/joker/godns/utils"
@ -49,8 +51,13 @@ func NewFileProvider(file string, ttl time.Duration) Provider {
return fp
}
func (f *FileHosts) Get(domain string) ([]string, time.Duration, bool) {
log.Debug("Checking file provider for %s", domain)
func (f *FileHosts) Get(queryType uint16, domain string) ([]string, time.Duration, bool) {
log.Debug("Checking file provider for %s : %s", queryType, domain)
// Does not support CNAME/TXT/etc
if queryType != dns.TypeA && queryType != dns.TypeAAAA {
return nil, zeroDuration, false
}
f.mu.RLock()
defer f.mu.RUnlock()
@ -77,6 +84,10 @@ func (f *FileHosts) Get(domain string) ([]string, time.Duration, bool) {
return nil, time.Duration(0), false
}
func (f *FileHosts) Set(t, domain, value string) (bool, error) {
return false, errors.New("file provider does not support setting values")
}
var (
hostRegexp = regexp.MustCompile("^(.*?)\\s+(.*)$")
)

View File

@ -2,6 +2,7 @@ package hosts
import (
"github.com/go-redis/redis/v7"
"github.com/miekg/dns"
"github.com/ryanuber/go-glob"
"meow.tf/joker/godns/log"
"strings"
@ -33,9 +34,14 @@ func NewRedisProvider(rc *redis.Client, key string, ttl time.Duration) Provider
return rh
}
func (r *RedisHosts) Get(domain string) ([]string, time.Duration, bool) {
func (r *RedisHosts) Get(queryType uint16, domain string) ([]string, time.Duration, bool) {
log.Debug("Checking redis provider for %s", domain)
// Don't support queries other than A/AAAA for now
if queryType != dns.TypeA || queryType != dns.TypeAAAA {
return nil, zeroDuration, false
}
r.mu.RLock()
defer r.mu.RUnlock()
@ -62,7 +68,7 @@ func (r *RedisHosts) Get(domain string) ([]string, time.Duration, bool) {
return nil, time.Duration(0), false
}
func (r *RedisHosts) Set(domain, ip string) (bool, error) {
func (r *RedisHosts) Set(t, domain, ip string) (bool, error) {
r.mu.Lock()
defer r.mu.Unlock()
return r.redis.HSet(r.key, strings.ToLower(domain), []byte(ip)).Result()