mirror of https://github.com/hashicorp/consul
406 lines
9.0 KiB
Go
406 lines
9.0 KiB
Go
|
// Copyright (c) HashiCorp, Inc.
|
||
|
// SPDX-License-Identifier: BUSL-1.1
|
||
|
|
||
|
package dns
|
||
|
|
||
|
import (
|
||
|
"net"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/miekg/dns"
|
||
|
)
|
||
|
|
||
|
func Test_HandleRequest_ADDR(t *testing.T) {
|
||
|
testCases := []HandleTestCase{
|
||
|
{
|
||
|
name: "test A 'addr.' query, ipv4 response",
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul", // "intentionally missing the trailing dot"
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Answer: []dns.RR{
|
||
|
&dns.A{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
A: net.ParseIP("192.0.2.10"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test AAAA 'addr.' query, ipv4 response",
|
||
|
// Since we asked for an AAAA record, the A record that resolves from the address is attached as an extra
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul",
|
||
|
Qtype: dns.TypeAAAA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeAAAA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Extra: []dns.RR{
|
||
|
&dns.A{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
A: net.ParseIP("192.0.2.10"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test SRV 'addr.' query, ipv4 response",
|
||
|
// Since we asked for a SRV record, the A record that resolves from the address is attached as an extra
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul",
|
||
|
Qtype: dns.TypeSRV,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeSRV,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Extra: []dns.RR{
|
||
|
&dns.A{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
A: net.ParseIP("192.0.2.10"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test ANY 'addr.' query, ipv4 response",
|
||
|
// The response to ANY should look the same as the A response
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul",
|
||
|
Qtype: dns.TypeANY,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeANY,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Answer: []dns.RR{
|
||
|
&dns.A{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "c000020a.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
A: net.ParseIP("192.0.2.10"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test AAAA 'addr.' query, ipv6 response",
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
|
||
|
Qtype: dns.TypeAAAA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeAAAA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Answer: []dns.RR{
|
||
|
&dns.AAAA{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeAAAA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test A 'addr.' query, ipv6 response",
|
||
|
// Since we asked for an A record, the AAAA record that resolves from the address is attached as an extra
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Extra: []dns.RR{
|
||
|
&dns.AAAA{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeAAAA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test SRV 'addr.' query, ipv6 response",
|
||
|
// Since we asked for an SRV record, the AAAA record that resolves from the address is attached as an extra
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
|
||
|
Qtype: dns.TypeSRV,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeSRV,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Extra: []dns.RR{
|
||
|
&dns.AAAA{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeAAAA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test ANY 'addr.' query, ipv6 response",
|
||
|
// The response to ANY should look the same as the AAAA response
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul",
|
||
|
Qtype: dns.TypeANY,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeANY,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Answer: []dns.RR{
|
||
|
&dns.AAAA{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "20010db800010002cafe000000001337.addr.dc1.consul.",
|
||
|
Rrtype: dns.TypeAAAA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 123,
|
||
|
},
|
||
|
AAAA: net.ParseIP("2001:db8:1:2:cafe::1337"),
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
{
|
||
|
name: "test malformed 'addr.' query",
|
||
|
request: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
},
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000.addr.dc1.consul", // too short
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
response: &dns.Msg{
|
||
|
MsgHdr: dns.MsgHdr{
|
||
|
Opcode: dns.OpcodeQuery,
|
||
|
Response: true,
|
||
|
Rcode: dns.RcodeNameError, // NXDOMAIN
|
||
|
Authoritative: true,
|
||
|
},
|
||
|
Compress: true,
|
||
|
Question: []dns.Question{
|
||
|
{
|
||
|
Name: "c000.addr.dc1.consul.",
|
||
|
Qtype: dns.TypeA,
|
||
|
Qclass: dns.ClassINET,
|
||
|
},
|
||
|
},
|
||
|
Ns: []dns.RR{
|
||
|
&dns.SOA{
|
||
|
Hdr: dns.RR_Header{
|
||
|
Name: "consul.",
|
||
|
Rrtype: dns.TypeSOA,
|
||
|
Class: dns.ClassINET,
|
||
|
Ttl: 4,
|
||
|
},
|
||
|
Ns: "ns.consul.",
|
||
|
Serial: uint32(time.Now().Unix()),
|
||
|
Mbox: "hostmaster.consul.",
|
||
|
Refresh: 1,
|
||
|
Expire: 3,
|
||
|
Retry: 2,
|
||
|
Minttl: 4,
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
}
|
||
|
|
||
|
for _, tc := range testCases {
|
||
|
t.Run(tc.name, func(t *testing.T) {
|
||
|
runHandleTestCases(t, tc)
|
||
|
})
|
||
|
}
|
||
|
}
|