package synthetic import ( "context" "fmt" "github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/test" "github.com/miekg/dns" "net" "testing" ) // todo: // 1. A lookup for v6 address func TestServeDNSv4(t *testing.T) { ip, ipNet, err := net.ParseCIDR("192.0.2.0/24") if err != nil { log.Fatal(err) } s := synthetic{ Next: test.ErrorHandler(), Config: syntheticConfig{ net: []*net.IPNet{{IP: ip, Mask: ipNet.Mask}}, forward: "example.com", prefix: "ip-", }, } testCases := []struct { qname string qtype uint16 wantrcode int wantAnswer []string wantTTL uint32 }{ { qname: "ip-192-0-2-0.example.com", qtype: dns.TypeA, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"192.0.2.0"}, wantTTL: 0, }, { qname: "ip-192-0-2-255.example.com", qtype: dns.TypeA, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"192.0.2.255"}, wantTTL: 0, }, { qname: "ip-203-0-113-100.example.com", qtype: dns.TypeA, wantrcode: dns.RcodeServerFailure, wantAnswer: nil, wantTTL: 0, }, { qname: "123.2.0.192.in-addr.arpa.", qtype: dns.TypePTR, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"ip-192-0-2-123.example.com."}, wantTTL: 0, }, { qname: "ip-2001-db8-abcd--.example.com", qtype: dns.TypeA, wantrcode: dns.RcodeServerFailure, wantAnswer: nil, wantTTL: 0, }, } for i, tc := range testCases { errorMsgPrefix := fmt.Sprintf("Test case %v for '%v' failed. Expected", i, tc.qname) ctx := context.TODO() w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion(tc.qname, tc.qtype) rc, err := s.ServeDNS(ctx, w, r) if err != nil { t.Errorf("%v no error, but got %v", errorMsgPrefix, err) } if rc != tc.wantrcode { t.Errorf("%v rcode %v, but got %v", errorMsgPrefix, tc.wantrcode, rc) } if len(w.Msg.Answer) == 0 && tc.wantAnswer != nil { t.Errorf("%v an answer, but got none", errorMsgPrefix) continue } if tc.wantAnswer == nil { if len(w.Msg.Answer) > 0 { t.Errorf("%v no answer, but got %v", errorMsgPrefix, w.Msg.Answer[0]) } continue } if w.Msg.Answer[0].Header().Ttl != 0 { t.Errorf("%v TTL to be 0, but got %v", errorMsgPrefix, w.Msg.Answer[0].Header().Ttl) } if w.Msg.Answer[0].Header().Name != tc.qname { t.Errorf("%v Name to be %s, but got %s", errorMsgPrefix, tc.qname, w.Msg.Answer[0].Header().Name) } if w.Msg.Answer[0].Header().Rrtype != tc.qtype { t.Errorf("%v Type to be %d, but got %d", errorMsgPrefix, tc.qtype, w.Msg.Answer[0].Header().Rrtype) } if w.Msg.Answer[0].Header().Ttl != tc.wantTTL { t.Errorf("%v TTL to be %d, but got %d", errorMsgPrefix, tc.wantTTL, w.Msg.Answer[0].Header().Ttl) } switch tc.qtype { case dns.TypeA: if w.Msg.Answer[0].(*dns.A).A.String() != tc.wantAnswer[0] { t.Errorf("%v answer %s, but got %s", errorMsgPrefix, tc.wantAnswer[0], w.Msg.Answer[0].(*dns.A).A.String()) } case dns.TypePTR: if w.Msg.Answer[0].(*dns.PTR).Ptr != tc.wantAnswer[0] { t.Errorf("%v answer %s, but got %s", errorMsgPrefix, tc.wantAnswer[0], w.Msg.Answer[0].(*dns.PTR).Ptr) } } } } // todo: // 2. AAAA lookup for v4 address func TestServeDNSv6(t *testing.T) { ip, ipNet, err := net.ParseCIDR("2001:db8:abcd::/48") if err != nil { log.Fatal(err) } s := synthetic{ Next: test.ErrorHandler(), Config: syntheticConfig{ net: []*net.IPNet{{IP: ip, Mask: ipNet.Mask}}, forward: "example.com.", ttl: 1800, prefix: "ip6-", }, } testCases := []struct { qname string qtype uint16 wantrcode int wantAnswer []string wantTTL uint32 }{ { qname: "ip6-2001-db8-abcd--.example.com", qtype: dns.TypeAAAA, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"2001:db8:abcd::"}, wantTTL: 1800, }, { qname: "ip6-2001-db8-abcd-1234-4567-890a-bcde-f123.example.com", qtype: dns.TypeAAAA, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"2001:db8:abcd:1234:4567:890a:bcde:f123"}, wantTTL: 1800, }, { qname: "ip6-2001-db8-1234--.example.com", qtype: dns.TypeAAAA, wantrcode: dns.RcodeServerFailure, wantAnswer: nil, wantTTL: 1800, }, { qname: "3.2.1.f.e.d.c.b.a.0.9.8.7.6.5.4.4.3.2.1.d.c.b.a.8.b.d.0.1.0.0.2.ip6.arpa.", qtype: dns.TypePTR, wantrcode: dns.RcodeSuccess, wantAnswer: []string{"ip6-2001-db8-abcd-1234-4567-890a-bcde-f123.example.com."}, wantTTL: 1800, }, { qname: "ip6-192-0-2-0.example.com", qtype: dns.TypeAAAA, wantrcode: dns.RcodeServerFailure, wantAnswer: nil, wantTTL: 0, }, } for i, tc := range testCases { errorMsgPrefix := fmt.Sprintf("Test case %v for '%v' failed. Expected", i, tc.qname) ctx := context.TODO() w := dnstest.NewRecorder(&test.ResponseWriter{}) r := new(dns.Msg) r.SetQuestion(tc.qname, tc.qtype) rc, err := s.ServeDNS(ctx, w, r) if err != nil { t.Errorf("%v no error, but got %v", errorMsgPrefix, err) } if rc != tc.wantrcode { t.Errorf("%v rcode %v, but got %v", errorMsgPrefix, tc.wantrcode, rc) } if len(w.Msg.Answer) == 0 && tc.wantAnswer != nil { t.Errorf("%v an answer, but got none", errorMsgPrefix) continue } if tc.wantAnswer == nil { if len(w.Msg.Answer) > 0 { t.Errorf("%v no answer, but got %v", errorMsgPrefix, w.Msg.Answer[0]) } continue } if w.Msg.Answer[0].Header().Name != tc.qname { t.Errorf("%v Name to be %s, but got %s", errorMsgPrefix, tc.qname, w.Msg.Answer[0].Header().Name) } if w.Msg.Answer[0].Header().Rrtype != tc.qtype { t.Errorf("%v Type to be %d, but got %d", errorMsgPrefix, tc.qtype, w.Msg.Answer[0].Header().Rrtype) } if w.Msg.Answer[0].Header().Ttl != tc.wantTTL { t.Errorf("%v TTL to be %d, but got %d", errorMsgPrefix, tc.wantTTL, w.Msg.Answer[0].Header().Ttl) } switch tc.qtype { case dns.TypeA: if w.Msg.Answer[0].(*dns.A).A.String() != tc.wantAnswer[0] { t.Errorf("%v answer %s, but got %s", errorMsgPrefix, tc.wantAnswer[0], w.Msg.Answer[0].(*dns.A).A.String()) } case dns.TypePTR: if w.Msg.Answer[0].(*dns.PTR).Ptr != tc.wantAnswer[0] { t.Errorf("%v answer %s, but got %s", errorMsgPrefix, tc.wantAnswer[0], w.Msg.Answer[0].(*dns.PTR).Ptr) } } } }