dns/responder/reflector-responder.go

121 lines
3.1 KiB
Go

/* A name server which sends back the IP address of its client, the
recursive resolver. When queried for type TXT, it sends back the text
form of the address. When queried for type A (resp. AAAA), it sends
back the IPv4 (resp. v6) address.
Similar services: whoami.ultradns.net, whoami.akamai.net. Also (but it
is not their normal goal): rs.dns-oarc.net, porttest.dns-oarc.net,
amiopen.openresolvers.org.
Stephane Bortzmeyer <stephane+grong@bortzmeyer.org>
*/
package responder
import (
"net"
"reflect"
"./types"
)
// Compile-time options
const includesPort = false // If false, sends only the address for TXT queries.
// If true, includes the UDP or TCP port.
// TODO: allow to secify the Qname it must respond to
func txtRecord(client net.Addr) []byte {
sclient := client.String()
if !includesPort {
tcpAddr, _ := net.ResolveTCPAddr(sclient)
sclient = tcpAddr.IP.String()
}
return types.ToTXT(sclient)
}
func txtSection(qname string, client net.Addr) (result types.RR) {
result.Name = qname
result.Type = types.TXT
result.Class = types.IN
result.TTL = 0
result.Data = txtRecord(client)
return
}
func addressSection(qname string, client net.IP) (result types.RR) {
result.Name = qname
result.Type = types.A
result.Class = types.IN
result.TTL = 0
result.Data = client
return
}
func aaaaSection(qname string, client net.IP) (result types.RR) {
result.Name = qname
result.Type = types.AAAA
result.Class = types.IN
result.TTL = 0
result.Data = client
return
}
func Respond(query types.DNSquery, config map[string]interface{}) types.DNSresponse {
var (
result types.DNSresponse
)
result.Ansection = nil
tcpAddr, _ := net.ResolveTCPAddr(query.Client.String())
ipaddressV4 := tcpAddr.IP.To4()
zonei, zoneset := config["zonename"]
zone := ""
if zoneset {
zone = reflect.NewValue(zonei).(*reflect.StringValue).Get()
}
switch {
case query.Qclass != types.IN:
result.Responsecode = types.SERVFAIL
case zone != "" && query.Qname != zone:
result.Responsecode = types.SERVFAIL
case query.Qtype == types.A:
result.Responsecode = types.NOERROR
if ipaddressV4 != nil {
ancount := 1
result.Ansection = make([]types.RR, ancount)
result.Ansection[0] = addressSection(query.Qname, ipaddressV4)
} else {
// ancount := 0
}
case query.Qtype == types.AAAA:
result.Responsecode = types.NOERROR
if ipaddressV4 == nil {
ancount := 1
result.Ansection = make([]types.RR, ancount)
result.Ansection[0] = aaaaSection(query.Qname, tcpAddr.IP)
} else {
// ancount := 0
}
case query.Qtype == types.TXT:
result.Responsecode = types.NOERROR
ancount := 1
result.Ansection = make([]types.RR, ancount)
result.Ansection[0] = txtSection(query.Qname, query.Client)
case query.Qtype == types.ALL:
result.Responsecode = types.NOERROR
ancount := 2
result.Ansection = make([]types.RR, ancount)
result.Ansection[0] = txtSection(query.Qname, query.Client)
if ipaddressV4 == nil {
result.Ansection[1] = aaaaSection(query.Qname, tcpAddr.IP)
} else {
result.Ansection[1] = addressSection(query.Qname, ipaddressV4)
}
default:
result.Responsecode = types.NOERROR
}
return result
}
func Init(firstoption int) {
}