plugin/hosts: create inline map in setup (#3071)

* plugin/hosts: create inline map in setup

The inline map wasn't create in the setup.go fuction leading to a crash,
which is masked by a recover (but leads to a SERVFAIL, and not logging
the request).

Various other simplifications.

host plugin could use some test that actually cover these edgecases.

Signed-off-by: Miek Gieben <miek@miek.nl>

* PR review changes

Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
Miek Gieben 2019-07-31 19:37:09 +00:00 committed by GitHub
parent 45e17c325c
commit 07f016191d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 23 additions and 28 deletions

View file

@ -15,6 +15,9 @@ The plugin reloads the content of the hosts file every 5 seconds. Upon reload, C
new definitions. Should the file be deleted, any inlined content will continue to be served. When
the file is restored, it will then again be used.
If you want to pass the request to the rest of the plugin chain if there is no match in the *hosts*
plugin, you must specify the `fallthrough` option.
This plugin can only be used once per Server Block.
## The hosts file
@ -60,7 +63,9 @@ hosts [FILE [ZONES...]] {
then all of them will be treated as the additional content for hosts file. The specified hosts
file path will still be read but entries will be overridden.
* `ttl` change the DNS TTL of the records generated (forward and reverse). The default is 3600 seconds (1 hour).
* `reload` change the period between each hostsfile reload. A time of zero seconds disable the feature. Examples of valid durations: "300ms", "1.5h" or "2h45m" are valid duration with units "ns" (nanosecond), "us" (or "µs" for microsecond), "ms" (millisecond), "s" (second), "m" (minute), "h" (hour).
* `reload` change the period between each hostsfile reload. A time of zero seconds disables the
feature. Examples of valid durations: "300ms", "1.5h" or "2h45m". See Go's
[time](https://godoc.org/time). package.
* `no_reverse` disable the automatic generation of the `in-addr.arpa` or `ip6.arpa` entries for the hosts
* `fallthrough` If zone matches and no record can be generated, pass request to the next plugin.
If **[ZONES...]** is omitted, then fallthrough happens for all zones for which the plugin

View file

@ -29,8 +29,8 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
zone := plugin.Zones(h.Origins).Matches(qname)
if zone == "" {
// PTR zones don't need to be specified in Origins
if state.Type() != "PTR" {
// PTR zones don't need to be specified in Origins.
if state.QType() != dns.TypePTR {
// if this doesn't match we need to fall through regardless of h.Fallthrough
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
}
@ -56,8 +56,10 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
if h.Fall.Through(qname) {
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
}
if !h.otherRecordsExist(state.QType(), qname) {
return dns.RcodeNameError, nil
// We want to send an NXDOMAIN, but because of /etc/hosts' setup we don't have a SOA, so we make it REFUSED
// to at least give an answer back to signals we're having problems resolving this.
if !h.otherRecordsExist(qname) {
return dns.RcodeServerFailure, nil
}
}
@ -70,23 +72,12 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
return dns.RcodeSuccess, nil
}
func (h Hosts) otherRecordsExist(qtype uint16, qname string) bool {
switch qtype {
case dns.TypeA:
if len(h.LookupStaticHostV6(qname)) > 0 {
return true
}
case dns.TypeAAAA:
if len(h.LookupStaticHostV4(qname)) > 0 {
return true
}
default:
if len(h.LookupStaticHostV4(qname)) > 0 {
return true
}
if len(h.LookupStaticHostV6(qname)) > 0 {
return true
}
func (h Hosts) otherRecordsExist(qname string) bool {
if len(h.LookupStaticHostV4(qname)) > 0 {
return true
}
if len(h.LookupStaticHostV6(qname)) > 0 {
return true
}
return false
}

View file

@ -73,13 +73,12 @@ func setup(c *caddy.Controller) error {
func hostsParse(c *caddy.Controller) (Hosts, error) {
config := dnsserver.GetConfig(c)
options := newOptions()
h := Hosts{
Hostsfile: &Hostsfile{
path: "/etc/hosts",
hmap: newMap(),
options: options,
inline: newMap(),
options: newOptions(),
},
}
@ -129,7 +128,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
case "fallthrough":
h.Fall.SetZonesFromArgs(c.RemainingArgs())
case "no_reverse":
options.autoReverse = false
h.options.autoReverse = false
case "ttl":
remaining := c.RemainingArgs()
if len(remaining) < 1 {
@ -142,7 +141,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
if ttl <= 0 || ttl > 65535 {
return h, c.Errf("ttl provided is invalid")
}
options.ttl = uint32(ttl)
h.options.ttl = uint32(ttl)
case "reload":
remaining := c.RemainingArgs()
if len(remaining) != 1 {
@ -155,7 +154,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
if reload < 0 {
return h, c.Errf("invalid negative duration for reload '%s'", remaining[0])
}
options.reload = reload
h.options.reload = reload
default:
if len(h.Fall.Zones) == 0 {
line := strings.Join(append([]string{c.Val()}, c.RemainingArgs()...), " ")