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:
parent
45e17c325c
commit
07f016191d
3 changed files with 23 additions and 28 deletions
|
@ -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
|
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.
|
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.
|
This plugin can only be used once per Server Block.
|
||||||
|
|
||||||
## The hosts file
|
## 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
|
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.
|
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).
|
* `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
|
* `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.
|
* `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
|
If **[ZONES...]** is omitted, then fallthrough happens for all zones for which the plugin
|
||||||
|
|
|
@ -29,8 +29,8 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
|
|
||||||
zone := plugin.Zones(h.Origins).Matches(qname)
|
zone := plugin.Zones(h.Origins).Matches(qname)
|
||||||
if zone == "" {
|
if zone == "" {
|
||||||
// PTR zones don't need to be specified in Origins
|
// PTR zones don't need to be specified in Origins.
|
||||||
if state.Type() != "PTR" {
|
if state.QType() != dns.TypePTR {
|
||||||
// if this doesn't match we need to fall through regardless of h.Fallthrough
|
// if this doesn't match we need to fall through regardless of h.Fallthrough
|
||||||
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
|
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) {
|
if h.Fall.Through(qname) {
|
||||||
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
|
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
|
||||||
}
|
}
|
||||||
if !h.otherRecordsExist(state.QType(), qname) {
|
// We want to send an NXDOMAIN, but because of /etc/hosts' setup we don't have a SOA, so we make it REFUSED
|
||||||
return dns.RcodeNameError, nil
|
// to at least give an answer back to signals we're having problems resolving this.
|
||||||
|
if !h.otherRecordsExist(qname) {
|
||||||
|
return dns.RcodeServerFailure, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,24 +72,13 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (
|
||||||
return dns.RcodeSuccess, nil
|
return dns.RcodeSuccess, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h Hosts) otherRecordsExist(qtype uint16, qname string) bool {
|
func (h Hosts) otherRecordsExist(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 {
|
if len(h.LookupStaticHostV4(qname)) > 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
if len(h.LookupStaticHostV6(qname)) > 0 {
|
if len(h.LookupStaticHostV6(qname)) > 0 {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,13 +73,12 @@ func setup(c *caddy.Controller) error {
|
||||||
func hostsParse(c *caddy.Controller) (Hosts, error) {
|
func hostsParse(c *caddy.Controller) (Hosts, error) {
|
||||||
config := dnsserver.GetConfig(c)
|
config := dnsserver.GetConfig(c)
|
||||||
|
|
||||||
options := newOptions()
|
|
||||||
|
|
||||||
h := Hosts{
|
h := Hosts{
|
||||||
Hostsfile: &Hostsfile{
|
Hostsfile: &Hostsfile{
|
||||||
path: "/etc/hosts",
|
path: "/etc/hosts",
|
||||||
hmap: newMap(),
|
hmap: newMap(),
|
||||||
options: options,
|
inline: newMap(),
|
||||||
|
options: newOptions(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,7 +128,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
|
||||||
case "fallthrough":
|
case "fallthrough":
|
||||||
h.Fall.SetZonesFromArgs(c.RemainingArgs())
|
h.Fall.SetZonesFromArgs(c.RemainingArgs())
|
||||||
case "no_reverse":
|
case "no_reverse":
|
||||||
options.autoReverse = false
|
h.options.autoReverse = false
|
||||||
case "ttl":
|
case "ttl":
|
||||||
remaining := c.RemainingArgs()
|
remaining := c.RemainingArgs()
|
||||||
if len(remaining) < 1 {
|
if len(remaining) < 1 {
|
||||||
|
@ -142,7 +141,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
|
||||||
if ttl <= 0 || ttl > 65535 {
|
if ttl <= 0 || ttl > 65535 {
|
||||||
return h, c.Errf("ttl provided is invalid")
|
return h, c.Errf("ttl provided is invalid")
|
||||||
}
|
}
|
||||||
options.ttl = uint32(ttl)
|
h.options.ttl = uint32(ttl)
|
||||||
case "reload":
|
case "reload":
|
||||||
remaining := c.RemainingArgs()
|
remaining := c.RemainingArgs()
|
||||||
if len(remaining) != 1 {
|
if len(remaining) != 1 {
|
||||||
|
@ -155,7 +154,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
|
||||||
if reload < 0 {
|
if reload < 0 {
|
||||||
return h, c.Errf("invalid negative duration for reload '%s'", remaining[0])
|
return h, c.Errf("invalid negative duration for reload '%s'", remaining[0])
|
||||||
}
|
}
|
||||||
options.reload = reload
|
h.options.reload = reload
|
||||||
default:
|
default:
|
||||||
if len(h.Fall.Zones) == 0 {
|
if len(h.Fall.Zones) == 0 {
|
||||||
line := strings.Join(append([]string{c.Val()}, c.RemainingArgs()...), " ")
|
line := strings.Join(append([]string{c.Val()}, c.RemainingArgs()...), " ")
|
||||||
|
|
Loading…
Add table
Reference in a new issue