aboutsummaryrefslogtreecommitdiff
path: root/plugin/hosts
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/hosts')
-rw-r--r--plugin/hosts/README.md15
-rw-r--r--plugin/hosts/hostsfile.go16
-rw-r--r--plugin/hosts/setup.go6
-rw-r--r--plugin/hosts/setup_test.go74
4 files changed, 109 insertions, 2 deletions
diff --git a/plugin/hosts/README.md b/plugin/hosts/README.md
index 60c738077..5e6ab0ec7 100644
--- a/plugin/hosts/README.md
+++ b/plugin/hosts/README.md
@@ -11,6 +11,7 @@ available hosts files that block access to advertising servers.
~~~
hosts [FILE [ZONES...]] {
+ [INLINE]
fallthrough
}
~~~
@@ -18,7 +19,10 @@ hosts [FILE [ZONES...]] {
* **FILE** the hosts file to read and parse. If the path is relative the path from the *root*
directive will be prepended to it. Defaults to /etc/hosts if omitted
* **ZONES** zones it should be authoritative for. If empty, the zones from the configuration block
- are used.
+ are used.
+* **INLINE** the hosts file contents inlined in Corefile. If there are any lines before fallthrough
+ 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 overrided.
* `fallthrough` If zone matches and no record can be generated, pass request to the next plugin.
## Examples
@@ -43,3 +47,12 @@ hosts example.hosts example.org example.net {
fallthrough
}
~~~
+
+Load hosts file inlined in Corefile.
+
+~~~
+hosts example.hosts example.org {
+ 10.0.0.1 example.org
+ fallthrough
+}
+~~~
diff --git a/plugin/hosts/hostsfile.go b/plugin/hosts/hostsfile.go
index 91e828099..0862711fe 100644
--- a/plugin/hosts/hostsfile.go
+++ b/plugin/hosts/hostsfile.go
@@ -53,6 +53,11 @@ type Hostsfile struct {
// We don't support old-classful IP address notation.
byAddr map[string][]string
+ // inline saves the hosts file is inlined in Corefile
+ // We need a copy here as we want to use inline to override
+ // the default /etc/hosts
+ inline []string
+
expire time.Time
path string
mtime time.Time
@@ -74,6 +79,10 @@ func (h *Hostsfile) ReadHosts() {
var file *os.File
if file, _ = os.Open(h.path); file == nil {
+ // If this is the first time then we will try to parse inline
+ if len(h.byAddr) == 0 && len(h.inline) > 0 {
+ h.Parse(nil)
+ }
return
}
defer file.Close()
@@ -92,7 +101,12 @@ func (h *Hostsfile) Parse(file io.Reader) {
hsv6 := make(map[string][]net.IP)
is := make(map[string][]string)
- scanner := bufio.NewScanner(file)
+ var readers []io.Reader
+ if file != nil {
+ readers = append(readers, file)
+ }
+ readers = append(readers, strings.NewReader(strings.Join(h.inline, "\n")))
+ scanner := bufio.NewScanner(io.MultiReader(readers...))
for scanner.Scan() {
line := scanner.Bytes()
if i := bytes.Index(line, []byte{'#'}); i >= 0 {
diff --git a/plugin/hosts/setup.go b/plugin/hosts/setup.go
index c7c0c728a..0c13140bb 100644
--- a/plugin/hosts/setup.go
+++ b/plugin/hosts/setup.go
@@ -4,6 +4,7 @@ import (
"log"
"os"
"path"
+ "strings"
"github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin"
@@ -80,6 +81,11 @@ func hostsParse(c *caddy.Controller) (Hosts, error) {
}
return h, c.ArgErr()
default:
+ if !h.Fallthrough {
+ line := strings.Join(append([]string{c.Val()}, c.RemainingArgs()...), " ")
+ h.inline = append(h.inline, line)
+ continue
+ }
return h, c.Errf("unknown property '%s'", c.Val())
}
}
diff --git a/plugin/hosts/setup_test.go b/plugin/hosts/setup_test.go
index a4c95b1c6..fefed6c72 100644
--- a/plugin/hosts/setup_test.go
+++ b/plugin/hosts/setup_test.go
@@ -84,3 +84,77 @@ func TestHostsParse(t *testing.T) {
}
}
}
+
+func TestHostsInlineParse(t *testing.T) {
+ tests := []struct {
+ inputFileRules string
+ shouldErr bool
+ expectedbyAddr map[string][]string
+ expectedFallthrough bool
+ }{
+ {
+ `hosts highly_unlikely_to_exist_hosts_file example.org {
+ 10.0.0.1 example.org
+ fallthrough
+ }`,
+ false,
+ map[string][]string{
+ `10.0.0.1`: {
+ `example.org.`,
+ },
+ },
+ true,
+ },
+ {
+ `hosts highly_unlikely_to_exist_hosts_file example.org {
+ 10.0.0.1 example.org
+ }`,
+ false,
+ map[string][]string{
+ `10.0.0.1`: {
+ `example.org.`,
+ },
+ },
+ false,
+ },
+ {
+ `hosts highly_unlikely_to_exist_hosts_file example.org {
+ fallthrough
+ 10.0.0.1 example.org
+ }`,
+ true,
+ map[string][]string{},
+ true,
+ },
+ }
+
+ for i, test := range tests {
+ c := caddy.NewTestController("dns", test.inputFileRules)
+ h, err := hostsParse(c)
+
+ if err == nil && test.shouldErr {
+ t.Fatalf("Test %d expected errors, but got no error", i)
+ } else if err != nil && !test.shouldErr {
+ t.Fatalf("Test %d expected no errors, but got '%v'", i, err)
+ } else if !test.shouldErr {
+ if h.Fallthrough != test.expectedFallthrough {
+ t.Fatalf("Test %d expected fallthrough of %v, got %v", i, test.expectedFallthrough, h.Fallthrough)
+ }
+ for k, expectedVal := range test.expectedbyAddr {
+ if val, ok := h.byAddr[k]; !ok {
+ t.Fatalf("Test %d expected %v, got no entry", i, k)
+ } else {
+ if len(expectedVal) != len(val) {
+ t.Fatalf("Test %d expected %v records for %v, got %v", i, len(expectedVal), k, len(val))
+ }
+ for j := range expectedVal {
+ if expectedVal[j] != val[j] {
+ t.Fatalf("Test %d expected %v for %v, got %v", i, expectedVal[j], j, val[j])
+ }
+ }
+ }
+ }
+ }
+ }
+
+}