plugin/hosts provide more configuration flexibility (#2535)

* plugin/hosts provide more configuration flexibility

This patch adds few features to the host plugin
 * no-reverse (both as first argument on the plugin line and inline)
   disable the automatic generation of reserve entries for hosts
 * ttl <duration> (inline only atm)
   allows to change the default ttl (default 5 minutes)
 * reload <duration> (inline only atm)
   allows to change the reloading interval (default 5s)

* plugin/hosts remove superfluous parameters to parse
This commit is contained in:
Thomas Mangin
2019-02-12 16:09:33 +00:00
committed by Pat Moroney
parent e47d881461
commit 4b402e000d
6 changed files with 163 additions and 70 deletions

View File

@@ -32,6 +32,26 @@ func absDomainName(b string) string {
return plugin.Name(b).Normalize()
}
type options struct {
// automatically generate IP to Hostname PTR entries
// for host entries we parse
autoReverse bool
// The TTL of the record we generate
ttl uint32
// The time between two reload of the configuration
reload time.Duration
}
func newOptions() *options {
return &options{
autoReverse: true,
ttl: 3600,
reload: durationOf5s,
}
}
type hostsMap struct {
// Key for the list of literal IP addresses must be a host
// name. It would be part of DNS labels, a FQDN or an absolute
@@ -46,6 +66,11 @@ type hostsMap struct {
byAddr map[string][]string
}
const (
durationOf0s = time.Duration(0)
durationOf5s = time.Duration(5 * time.Second)
)
func newHostsMap() *hostsMap {
return &hostsMap{
byNameV4: make(map[string][]net.IP),
@@ -90,6 +115,8 @@ type Hostsfile struct {
// mtime and size are only read and modified by a single goroutine
mtime time.Time
size int64
options *options
}
// readHosts determines if the cached data needs to be updated based on the size and modification time of the hostsfile.
@@ -106,7 +133,7 @@ func (h *Hostsfile) readHosts() {
return
}
newMap := h.parse(file, h.inline)
newMap := h.parse(file)
log.Debugf("Parsed hosts file into %d entries", newMap.Len())
h.Lock()
@@ -124,13 +151,12 @@ func (h *Hostsfile) initInline(inline []string) {
return
}
hmap := newHostsMap()
h.inline = h.parse(strings.NewReader(strings.Join(inline, "\n")), hmap)
h.inline = h.parse(strings.NewReader(strings.Join(inline, "\n")))
*h.hmap = *h.inline
}
// Parse reads the hostsfile and populates the byName and byAddr maps.
func (h *Hostsfile) parse(r io.Reader, override *hostsMap) *hostsMap {
func (h *Hostsfile) parse(r io.Reader) *hostsMap {
hmap := newHostsMap()
scanner := bufio.NewScanner(r)
@@ -163,22 +189,22 @@ func (h *Hostsfile) parse(r io.Reader, override *hostsMap) *hostsMap {
default:
continue
}
if !h.options.autoReverse {
continue
}
hmap.byAddr[addr.String()] = append(hmap.byAddr[addr.String()], name)
}
}
if override == nil {
return hmap
for name := range h.hmap.byNameV4 {
hmap.byNameV4[name] = append(hmap.byNameV4[name], h.hmap.byNameV4[name]...)
}
for name := range h.hmap.byNameV4 {
hmap.byNameV6[name] = append(hmap.byNameV6[name], h.hmap.byNameV6[name]...)
}
for name := range override.byNameV4 {
hmap.byNameV4[name] = append(hmap.byNameV4[name], override.byNameV4[name]...)
}
for name := range override.byNameV4 {
hmap.byNameV6[name] = append(hmap.byNameV6[name], override.byNameV6[name]...)
}
for addr := range override.byAddr {
hmap.byAddr[addr] = append(hmap.byAddr[addr], override.byAddr[addr]...)
for addr := range h.hmap.byAddr {
hmap.byAddr[addr] = append(hmap.byAddr[addr], h.hmap.byAddr[addr]...)
}
return hmap
@@ -199,32 +225,34 @@ func ipVersion(s string) int {
return 0
}
// LookupStaticHostV4 looks up the IPv4 addresses for the given host from the hosts file.
func (h *Hostsfile) LookupStaticHostV4(host string) []net.IP {
// LookupStaticHost looks up the IP addresses for the given host from the hosts file.
func (h *Hostsfile) lookupStaticHost(hmapByName map[string][]net.IP, host string) []net.IP {
fqhost := absDomainName(host)
h.RLock()
defer h.RUnlock()
if len(h.hmap.byNameV4) != 0 {
if ips, ok := h.hmap.byNameV4[absDomainName(host)]; ok {
ipsCp := make([]net.IP, len(ips))
copy(ipsCp, ips)
return ipsCp
}
if len(hmapByName) == 0 {
return nil
}
return nil
ips, ok := hmapByName[fqhost]
if !ok {
return nil
}
ipsCp := make([]net.IP, len(ips))
copy(ipsCp, ips)
return ipsCp
}
// LookupStaticHostV4 looks up the IPv4 addresses for the given host from the hosts file.
func (h *Hostsfile) LookupStaticHostV4(host string) []net.IP {
return h.lookupStaticHost(h.hmap.byNameV4, host)
}
// LookupStaticHostV6 looks up the IPv6 addresses for the given host from the hosts file.
func (h *Hostsfile) LookupStaticHostV6(host string) []net.IP {
h.RLock()
defer h.RUnlock()
if len(h.hmap.byNameV6) != 0 {
if ips, ok := h.hmap.byNameV6[absDomainName(host)]; ok {
ipsCp := make([]net.IP, len(ips))
copy(ipsCp, ips)
return ipsCp
}
}
return nil
return h.lookupStaticHost(h.hmap.byNameV6, host)
}
// LookupStaticAddr looks up the hosts for the given address from the hosts file.
@@ -235,12 +263,14 @@ func (h *Hostsfile) LookupStaticAddr(addr string) []string {
if addr == "" {
return nil
}
if len(h.hmap.byAddr) != 0 {
if hosts, ok := h.hmap.byAddr[addr]; ok {
hostsCp := make([]string, len(hosts))
copy(hostsCp, hosts)
return hostsCp
}
if len(h.hmap.byAddr) == 0 {
return nil
}
return nil
hosts, ok := h.hmap.byAddr[addr]
if !ok {
return nil
}
hostsCp := make([]string, len(hosts))
copy(hostsCp, hosts)
return hostsCp
}