osbase/net/dns: add new DNS server
This adds a new DNS server service, which will replace CoreDNS. The
service has built-in handlers for certain names, but all other names
will be handled by runtime configurable handlers.
Change-Id: I4184d11422496e899794ef658ca1450e7bb01471
Reviewed-on: https://review.monogon.dev/c/monogon/+/3126
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/osbase/net/dns/name_test.go b/osbase/net/dns/name_test.go
new file mode 100644
index 0000000..fab7bba
--- /dev/null
+++ b/osbase/net/dns/name_test.go
@@ -0,0 +1,155 @@
+package dns
+
+import (
+ "testing"
+)
+
+func TestIsSubDomain(t *testing.T) {
+ cases := []struct {
+ parent, child string
+ expected bool
+ }{
+ {".", ".", true},
+ {".", "test.", true},
+ {"example.com.", "example.com.", true},
+ {"example.com.", "www.example.com.", true},
+ {"example.com.", "xample.com.", false},
+ {"example.com.", "www.axample.com.", false},
+ {"example.com.", "wwwexample.com.", false},
+ {"example.com.", `www\.example.com.`, false},
+ {"example.com.", `www\\.example.com.`, true},
+ }
+ for _, c := range cases {
+ if IsSubDomain(c.parent, c.child) != c.expected {
+ t.Errorf("IsSubDomain(%q, %q): expected %v", c.parent, c.child, c.expected)
+ }
+ }
+}
+
+func TestSplitLastLabel(t *testing.T) {
+ cases := []struct {
+ name, rest, label string
+ }{
+ {"", "", ""},
+ {".", "", ""},
+ {"com.", "", "com"},
+ {"www.example.com", "www.example.", "com"},
+ {"www.example.com.", "www.example.", "com"},
+ {`www.example\.com.`, "www.", `example\.com`},
+ {`www.example\\.com.`, `www.example\\.`, "com"},
+ }
+ for _, c := range cases {
+ rest, label := SplitLastLabel(c.name)
+ if rest != c.rest || label != c.label {
+ t.Errorf("SplitLastLabel(%q) = (%q, %q), expected (%q, %q)", c.name, rest, label, c.rest, c.label)
+ }
+ }
+}
+
+func TestParseReverse(t *testing.T) {
+ cases := []struct {
+ name string
+ ip string
+ bits int
+ extra bool
+ }{
+ {"example.", "invalid IP", 0, false},
+ {"0.10.200.255.in-addr.arpa.", "255.200.10.0", 32, false},
+ {"7.6.45.123.in-addr.arpa.", "123.45.6.7", 32, false},
+ {"6.45.123.in-addr.arpa.", "123.45.6.0", 24, false},
+ {"45.123.in-addr.arpa.", "123.45.0.0", 16, false},
+ {"123.in-addr.arpa.", "123.0.0.0", 8, false},
+ {"in-addr.arpa.", "0.0.0.0", 0, false},
+ {"8.7.6.45.123.in-addr.arpa.", "123.45.6.7", 32, true}, // too many fields
+ {".6.45.123.in-addr.arpa.", "123.45.6.0", 24, true}, // empty field
+ {"7.06.45.123.in-addr.arpa.", "123.45.0.0", 16, true}, // leading 0
+ {"7.256.45.123.in-addr.arpa.", "123.45.0.0", 16, true}, // number too large
+ {"a6.45.123.in-addr.arpa.", "123.45.0.0", 16, true}, // invalid character
+ {`7\.6.45.123.in-addr.arpa.`, "123.45.0.0", 16, true}, // escaped .
+ {"0.6.45.123in-addr.arpa.", "invalid IP", 0, false}, // missing .
+ {
+ "0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
+ "::fedc:ba98:7654:3210",
+ 128,
+ false,
+ },
+ {
+ "1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
+ "::fedc:ba98:7654:3210",
+ 124,
+ false,
+ },
+ {
+ "2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
+ "::fedc:ba98:7654:3200",
+ 120,
+ false,
+ },
+ {
+ "3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.",
+ "::fedc:ba98:7654:3000",
+ 116,
+ false,
+ },
+ {
+ "2.ip6.arpa.",
+ "2000::",
+ 4,
+ false,
+ },
+ {
+ "ip6.arpa.",
+ "::",
+ 0,
+ false,
+ },
+ {
+ "0.0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", // too long
+ "::fedc:ba98:7654:3210",
+ 128,
+ true,
+ },
+ {
+ "01.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", // missing dot
+ "::fedc:ba98:7654:3200",
+ 120,
+ true,
+ },
+ {
+ "001.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", // missing dot
+ "::fedc:ba98:7654:3200",
+ 120,
+ true,
+ },
+ {
+ `0.1\.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.`, // escaped dot
+ "::fedc:ba98:7654:3000",
+ 116,
+ true,
+ },
+ {
+ "g.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.", // invalid character
+ "::fedc:ba98:7654:3210",
+ 124,
+ true,
+ },
+ }
+ for _, c := range cases {
+ ip, bits, extra := ParseReverse(c.name)
+ if ip.String() != c.ip || bits != c.bits || extra != c.extra {
+ t.Errorf("ParseReverse(%q) = (%s, %v, %v), expected (%s, %v, %v)", c.name, ip, bits, extra, c.ip, c.bits, c.extra)
+ }
+ }
+}
+
+func BenchmarkParseReverseIPv4(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ParseReverse("7.6.45.123.in-addr.arpa.")
+ }
+}
+
+func BenchmarkParseReverseIPv6(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ ParseReverse("0.1.2.3.4.5.6.7.8.9.a.b.c.d.e.f.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.")
+ }
+}