Exemple #1
0
func rootZone(w dns.ResponseWriter, req *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(req)
	rr, _ := dns.NewRR(". 0 IN SOA a.root-servers.net. nstld.verisign-grs.com. 2016110600 1800 900 604800 86400")
	m.Ns = []dns.RR{rr}
	w.WriteMsg(m)
}
Exemple #2
0
// handleTest is used to handle DNS queries in the ".consul." domain
func (d *DNSServer) handleTest(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%v)", q, time.Now().Sub(s))
	}(time.Now())

	if !(q.Qtype == dns.TypeANY || q.Qtype == dns.TypeTXT) {
		return
	}
	if q.Name != testQuery {
		return
	}

	// Always respond with TXT "ok"
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = true
	header := dns.RR_Header{Name: q.Name, Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: 0}
	txt := &dns.TXT{header, []string{"ok"}}
	m.Answer = append(m.Answer, txt)
	d.addSOA(consulDomain, m)
	if err := resp.WriteMsg(m); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Exemple #3
0
func createRespMsg(query *dns.Msg) *dns.Msg {
	resp := new(dns.Msg)
	resp.SetReply(query)
	setCommonFlags(resp)

	return resp
}
Exemple #4
0
// handlePtr is used to handle "reverse" DNS queries
func (d *DNSServer) handlePtr(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%v) from client %s (%s)",
			q, time.Now().Sub(s), resp.RemoteAddr().String(),
			resp.RemoteAddr().Network())
	}(time.Now())

	// Setup the message response
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = (len(d.recursors) > 0)

	// Only add the SOA if requested
	if req.Question[0].Qtype == dns.TypeSOA {
		d.addSOA(d.domain, m)
	}

	datacenter := d.agent.config.Datacenter

	// Get the QName without the domain suffix
	qName := strings.ToLower(dns.Fqdn(req.Question[0].Name))

	args := structs.DCSpecificRequest{
		Datacenter: datacenter,
		QueryOptions: structs.QueryOptions{
			Token:      d.agent.config.ACLToken,
			AllowStale: d.config.AllowStale,
		},
	}
	var out structs.IndexedNodes

	// TODO: Replace ListNodes with an internal RPC that can do the filter
	// server side to avoid transferring the entire node list.
	if err := d.agent.RPC("Catalog.ListNodes", &args, &out); err == nil {
		for _, n := range out.Nodes {
			arpa, _ := dns.ReverseAddr(n.Address)
			if arpa == qName {
				ptr := &dns.PTR{
					Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: 0},
					Ptr: fmt.Sprintf("%s.node.%s.%s", n.Node, datacenter, d.domain),
				}
				m.Answer = append(m.Answer, ptr)
				break
			}
		}
	}

	// nothing found locally, recurse
	if len(m.Answer) == 0 {
		d.handleRecurse(resp, req)
		return
	}

	// Write out the complete response
	if err := resp.WriteMsg(m); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Exemple #5
0
// handleQUery is used to handle DNS queries in the configured domain
func (d *DNSServer) handleQuery(resp dns.ResponseWriter, req *dns.Msg) {
	q := req.Question[0]
	defer func(s time.Time) {
		d.logger.Printf("[DEBUG] dns: request for %v (%v)", q, time.Now().Sub(s))
	}(time.Now())

	// Switch to TCP if the client is
	network := "udp"
	if _, ok := resp.RemoteAddr().(*net.TCPAddr); ok {
		network = "tcp"
	}

	// Setup the message response
	m := new(dns.Msg)
	m.SetReply(req)
	m.Authoritative = true
	m.RecursionAvailable = (len(d.recursors) > 0)

	// Only add the SOA if requested
	if req.Question[0].Qtype == dns.TypeSOA {
		d.addSOA(d.domain, m)
	}

	// Dispatch the correct handler
	d.dispatch(network, req, m)

	// Write out the complete response
	if err := resp.WriteMsg(m); err != nil {
		d.logger.Printf("[WARN] dns: failed to respond: %v", err)
	}
}
Exemple #6
0
// handleDomain handles DNS queries that come to the cluster
func (d *DnsServer) handleDomain(w dns.ResponseWriter, r *dns.Msg) {
	dom, qType := parseQuestion(r)
	q := dns.TypeToString[qType] + " " + dom
	log.Printf("--> Internal: %s", q)

	m := new(dns.Msg)
	m.SetReply(r)
	m.Authoritative = true

	supported, found, recs := d.queryRR(qType, dom)
	if !supported {
		log.Printf("<-x %s: NOTIMP", q)
		m.SetRcode(r, dns.RcodeNotImplemented) // NOTIMP
	} else if !found {
		log.Printf("<-x %s: NXDOMAIN", q)
		m.SetRcode(r, dns.RcodeNameError) // NXDOMAIN
	} else {
		for _, rec := range recs {
			rr, err := rrtype.ToRR(qType, dom, rec)
			if err != nil {
				log.Printf("<-x %s SERVFAIL: record conv err: %v", q, err)
				m.SetRcode(r, dns.RcodeServerFailure)
				break
			} else {
				log.Printf("<-- %s: %s", q, rr.String())
				m.Answer = append(m.Answer, rr)
			}
		}
	}
	w.WriteMsg(m)
}
Exemple #7
0
// Create DNS packet with the config in line with the meta zone
// paper from Vixie
func metazone(w dns.ResponseWriter, req *dns.Msg, c *Config) {
	logPrintf("metazone command")

	// Only called when the class is CHAOS
	// PTR zone.	-> get a list of zone names

	// Top level zone stuff -- list them
	if strings.ToUpper(req.Question[0].Name) == "ZONE." {
		m := new(dns.Msg)
		m.SetReply(req)
		for _, z := range c.Zones {
			ptr, _ := dns.NewRR("zone. 0 CH PTR " + z.Origin)
			m.Answer = append(m.Answer, ptr)
		}
		w.WriteMsg(m)
		return
	}

	// Top level user stuff -- list them
	if strings.ToUpper(req.Question[0].Name) == "USER." {

	}

	// <zone>.ZONE.

	formerr(w, req)
	return
}
Exemple #8
0
func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) {
	addr := r.sb.ResolveName(name, ipType)
	if addr == nil {
		return nil, nil
	}

	log.Debugf("Lookup for %s: IP %v", name, addr)

	resp := new(dns.Msg)
	resp.SetReply(query)
	setCommonFlags(resp)

	if len(addr) > 1 {
		addr = shuffleAddr(addr)
	}
	if ipType == netutils.IPv4 {
		for _, ip := range addr {
			rr := new(dns.A)
			rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: respTTL}
			rr.A = ip
			resp.Answer = append(resp.Answer, rr)
		}
	} else {
		for _, ip := range addr {
			rr := new(dns.AAAA)
			rr.Hdr = dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: respTTL}
			rr.AAAA = ip
			resp.Answer = append(resp.Answer, rr)
		}
	}
	return resp, nil
}
func (c *Config) GenerateServeDNS(hostname string) func(dns.ResponseWriter, *dns.Msg) {
	if len(hostname) > 0 {
		if hostname[len(hostname)-1] != '.' {
			hostname += "."
		}
	}

	return func(w dns.ResponseWriter, r *dns.Msg) {
		m := new(dns.Msg)
		m.SetReply(r)
		m.Authoritative = true

		ip, err := c.GetOrLaunchInstance()
		if err != nil {
			// TODO: error handling
			log.Println("Error in GetOrLaunchInstance:", err)
			w.Close()
			return
		}

		rr := new(dns.A)
		rr.Hdr = dns.RR_Header{Name: hostname, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: uint32(c.MaxIdleTime.Seconds())}
		rr.A = ip

		m.Answer = []dns.RR{rr}
		w.WriteMsg(m)
	}
}
Exemple #10
0
func (s *DNS) handleDNSInternal(w dns.ResponseWriter, req *dns.Msg) {

	q := req.Question[0]

	if q.Qtype == dns.TypeA && q.Qclass == dns.ClassINET {
		if record, ok := s.cache.Get(q.Name); ok {

			log.Printf("Found internal record for %s", q.Name)

			m := new(dns.Msg)
			m.SetReply(req)
			rr_header := dns.RR_Header{
				Name:   q.Name,
				Rrtype: dns.TypeA,
				Class:  dns.ClassINET,
				Ttl:    0,
			}
			a := &dns.A{rr_header, net.ParseIP(record.ip)}
			m.Answer = append(m.Answer, a)
			w.WriteMsg(m)

			return
		}

		log.Printf("No internal record found for %s", q.Name)
		dns.HandleFailed(w, req)
	}

	log.Printf("Only handling type A requests, skipping")
	dns.HandleFailed(w, req)
}
Exemple #11
0
func handleDnsRequest(w dns.ResponseWriter, r *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(r)
	records := make([]dns.RR, 0)
	q := r.Question[0]

	if q.Qtype == dns.TypeA && strings.HasSuffix(q.Name, ".docker.") {
		docker, _ := dockerclient.NewDockerClient("unix:///var/run/docker.sock", &tls.Config{})
		name := strings.SplitN(q.Name, ".", 2)[0]
		containers, err := docker.ListContainers(false, false, fmt.Sprintf("{\"name\":[\"%s\"]}", name))
		if err != nil {
			log.Fatal(err)
		}
		for _, c := range containers {
			info, _ := docker.InspectContainer(c.Id)
			log.Printf("Container %s[%6s] has ip %s\n", name, info.Id, info.NetworkSettings.IPAddress)
			records = append(records,
				&dns.A{
					Hdr: dns.RR_Header{
						Name:   q.Name,
						Rrtype: dns.TypeA,
						Class:  dns.ClassINET,
						Ttl:    60},
					A: net.ParseIP(info.NetworkSettings.IPAddress),
				})
		}
	}

	m.Answer = append(m.Answer, records...)
	defer w.WriteMsg(m)
}
Exemple #12
0
func (s *DNS) handleReverseDNSLookup(w dns.ResponseWriter, req *dns.Msg) {

	q := req.Question[0]

	if q.Qtype == dns.TypePTR && q.Qclass == dns.ClassINET {

		if record, ok := s.cache.Get(q.Name); ok {

			log.Printf("Found internal record for %s", q.Name)

			m := new(dns.Msg)
			m.SetReply(req)
			rr_header := dns.RR_Header{
				Name:   q.Name,
				Rrtype: dns.TypePTR,
				Class:  dns.ClassINET,
				Ttl:    0,
			}

			a := &dns.PTR{rr_header, record.fqdn}
			m.Answer = append(m.Answer, a)
			w.WriteMsg(m)

			return

		}

		log.Printf("Forwarding request to external recursor for: %s", q.Name)

		// Forward the request
		s.handleDNSExternal(w, req)
	}

	dns.HandleFailed(w, req)
}
Exemple #13
0
// handlerFunc receives requests, looks up the result and returns what is found.
func handlerFunc(res dns.ResponseWriter, req *dns.Msg) {
	message := new(dns.Msg)
	switch req.Opcode {
	case dns.OpcodeQuery:
		message.SetReply(req)
		message.Compress = false
		message.Answer = make([]dns.RR, 0)

		for _, question := range message.Question {
			answers := answerQuestion(strings.ToLower(question.Name), question.Qtype)
			if len(answers) > 0 {
				for i := range answers {
					message.Answer = append(message.Answer, answers[i])
				}
			} else {
				// If there are no records, go back through and search for SOA records
				for _, question := range message.Question {
					answers := answerQuestion(strings.ToLower(question.Name), dns.TypeSOA)
					for i := range answers {
						message.Ns = append(message.Ns, answers[i])
					}
				}
			}
		}
		if len(message.Answer) == 0 && len(message.Ns) == 0 {
			message.Rcode = dns.RcodeNameError
		}
	default:
		message = message.SetRcode(req, dns.RcodeNotImplemented)
	}
	res.WriteMsg(message)
}
func handlerToAnswer(w dns.ResponseWriter, r *dns.Msg) {
	db, err := sql.Open("mysql", "inserter:qwerty@/dnsServerCache") //Handler for database
	if err != nil {
		panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
	}

	answer := new(dns.Msg) //Set answer to client
	answer.SetReply(r)     //Set reply flag and start collecting data for reply
	var answersAll []dns.RR
	answersAll = dbRespond(db, r.Question[0].String())
	if len(answersAll) != 0 {
		for _, answers := range answersAll {
			answer.Answer = append(answer.Answer, answers)
		}
	} else {
		client := new(dns.Client)
		var err1 error
		config, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
		answer, _, err1 = client.Exchange(r, config.Servers[0]+":"+config.Port)
		if err1 != nil {
			panic(err1.Error())
		}
		if r.Rcode != dns.RcodeSuccess {
			return
		}
		go dbWriter(answer.Answer, db, r.Question[0].String())
	}
	w.WriteMsg(answer)
}
Exemple #15
0
func (manager *DnsManager) dnsHandler(w dns.ResponseWriter, req *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(req)

	name := req.Question[0].Name
	name = strings.TrimSuffix(name, "."+manager.BaseName)

	manager.dbMutex.Lock()
	entry, ok := manager.db[name]
	manager.dbMutex.Unlock()

	if ok {
		switch req.Question[0].Qtype {
		case dns.TypeSRV:
			m.Answer = manager.makeAllSRV(entry)
		case dns.TypeA:
			m.Answer = manager.makeAllA(entry)
			if manager.PushSRV {
				m.Extra = manager.makeAllSRV(entry)
			}
		}
	}

	w.WriteMsg(m)
}
Exemple #16
0
Fichier : main.go Projet : axw/jns
func (s *jujuNameServer) handleRequest(w dns.ResponseWriter, r *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(r)
	for _, q := range r.Question {
		rr, err := s.answer(q)
		if err != nil {
			m.SetRcodeFormatError(r)
			t := new(dns.TXT)
			t.Hdr = dns.RR_Header{
				Name:   q.Name,
				Rrtype: dns.TypeTXT,
				Class:  dns.ClassNONE,
			}
			t.Txt = []string{err.Error()}
			m.Extra = append(m.Extra, t)
			continue
		} else if rr != nil {
			m.Answer = append(m.Answer, rr)
		}
	}
	m.Authoritative = true
	// recursion isn't really available, but it's apparently
	// necessary to set this to make nslookup happy.
	m.RecursionAvailable = true
	w.WriteMsg(m)
}
Exemple #17
0
// handleExternal handles DNS queries that are outside the cluster's domain such
// as the Public Internet.
func (d *DnsServer) handleExternal(w dns.ResponseWriter, r *dns.Msg) {
	dom, qType := parseQuestion(r)
	q := dns.TypeToString[qType] + " " + dom
	log.Printf("--> External: %s", q)

	if !d.recurse {
		log.Printf("<-x %s: SERVFAIL: recursion disabled", q)
		m := new(dns.Msg)
		m.SetReply(r)
		m.SetRcode(r, dns.RcodeServerFailure)
		m.Authoritative = false
		m.RecursionAvailable = false
		w.WriteMsg(m)
	} else {
		in, ns, err := d.queryExternal(r)
		if err != nil {
			log.Printf("<-x %s (@%s): SERVFAIL: %v", q, ns, err)
			m := new(dns.Msg)
			m.SetReply(r)
			m.SetRcode(r, dns.RcodeServerFailure)
			w.WriteMsg(m)
		} else {
			log.Printf("<-- %s (@%s): %d answers, %d extra, %d ns", q, ns, len(in.Answer), len(in.Extra), len(in.Ns))
			in.Compress = true
			w.WriteMsg(in)
		}
	}
}
func (h dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
	if len(r.Question) != 1 {
		h.t.Fatalf("bad: %#v", r.Question)
	}

	name := "join.service.consul."
	question := r.Question[0]
	if question.Name != name || question.Qtype != dns.TypeANY {
		h.t.Fatalf("bad: %#v", question)
	}

	m := new(dns.Msg)
	m.SetReply(r)
	m.Authoritative = true
	m.RecursionAvailable = false
	m.Answer = append(m.Answer, &dns.A{
		Hdr: dns.RR_Header{
			Name:   name,
			Rrtype: dns.TypeA,
			Class:  dns.ClassINET},
		A: net.ParseIP("127.0.0.1"),
	})
	m.Answer = append(m.Answer, &dns.AAAA{
		Hdr: dns.RR_Header{
			Name:   name,
			Rrtype: dns.TypeAAAA,
			Class:  dns.ClassINET},
		AAAA: net.ParseIP("2001:db8:a0b:12f0::1"),
	})
	if err := w.WriteMsg(m); err != nil {
		h.t.Fatalf("err: %v", err)
	}
}
Exemple #19
0
func (s *soa) TransferHandler(w dns.ResponseWriter, req *dns.Msg) {
	m := new(dns.Msg)
	m.SetReply(req)
	m.Answer = make([]dns.RR, 1)
	m.Answer[0] = test.SOA(fmt.Sprintf("%s IN SOA bla. bla. %d 0 0 0 0 ", testZone, s.serial))
	w.WriteMsg(m)
}
Exemple #20
0
// Instantiate a new answer as a reply of the passed message.
func (h *ENUMHandler) answerForRequest(message *dns.Msg) *dns.Msg {
	answer := new(dns.Msg)
	answer.SetReply(message)
	answer.Authoritative = true
	answer.RecursionAvailable = false
	return answer
}
Exemple #21
0
func handle(writer dns.ResponseWriter, request *dns.Msg) {
	message := new(dns.Msg)
	message.SetReply(request)
	message.SetRcode(message, dns.RcodeSuccess)
	question := request.Question[0]

	switch request.Opcode {
	case dns.OpcodeNotify:
		log.Println(fmt.Sprintf("Recieved NOTIFY for %s", question.Name))
		message = handle_notify(question, message, writer)
	case dns.OpcodeQuery:
		log.Println(fmt.Sprintf("Recieved QUERY for %s", question.Name))
		message = handle_query(question, message, writer)
	default:
		message = handle_error(message, writer, "REFUSED")
	}

	// Apparently this dns library takes the question out on
	// certain RCodes, like REFUSED, which is not right. So we reinsert it.
	message.Question[0].Name = question.Name
	message.Question[0].Qtype = question.Qtype
	message.Question[0].Qclass = question.Qclass
	message.MsgHdr.Opcode = request.Opcode

	// Send an authoritative answer
	message.MsgHdr.Authoritative = true

	writer.WriteMsg(message)
}
Exemple #22
0
func handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
	if *debug {
		Log.Printf("handleRequest: message: %+v\n", r)
	}

	m := new(dns.Msg)
	m.SetReply(r)
	m.Compress = false

	switch r.Opcode {
	case dns.OpcodeQuery:
		parseQuery(m)

	case dns.OpcodeUpdate:
		for _, question := range r.Question {
			for _, rr := range r.Ns {
				updateRecord(rr, &question)
			}
		}
	}

	if r.IsTsig() != nil {
		if w.TsigStatus() == nil {
			m.SetTsig(r.Extra[len(r.Extra)-1].(*dns.TSIG).Hdr.Name,
				dns.HmacMD5, 300, time.Now().Unix())
		} else {
			Log.Println("Status", w.TsigStatus().Error())
		}
	}

	w.WriteMsg(m)
}
Exemple #23
0
func (s *DNSServer) doHandle(w dns.ResponseWriter, r *dns.Msg) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)

	// Send empty response for empty requests
	if len(r.Question) == 0 {
		m.Ns = s.createSOA()
		return m
	}

	switch r.Question[0].Qtype {
	case dns.TypePTR:
		s.handlePTRRequest(r, m)
	case dns.TypeMX:
		s.handleMXRequest(r, m)
	case dns.TypeA:
		s.handleARequest(r, m)
	case dns.TypeSOA:
		m.Answer = s.createSOA()
	default:
		m.Ns = s.createSOA()
		m.SetRcode(r, dns.RcodeNotImplemented)
	}

	return m
}
Exemple #24
0
func makeReply(r *dns.Msg, as []dns.RR) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	m.RecursionAvailable = true
	m.Answer = as
	return m
}
Exemple #25
0
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU() * 4)
	for z, rr := range zones {
		rrx := rr.(*dns.SOA) // Needed to create the actual RR, and not an reference.
		dns.HandleFunc(z, func(w dns.ResponseWriter, r *dns.Msg) {
			m := new(dns.Msg)
			m.SetReply(r)
			m.Authoritative = true
			m.Ns = []dns.RR{rrx}
			w.WriteMsg(m)
		})
	}
	go func() {
		err := dns.ListenAndServe(":8053", "tcp", nil)
		if err != nil {
			log.Fatal("Failed to set tcp listener %s\n", err.Error())
		}
	}()
	go func() {
		err := dns.ListenAndServe(":8053", "udp", nil)
		if err != nil {
			log.Fatal("Failed to set udp listener %s\n", err.Error())
		}
	}()
	sig := make(chan os.Signal)
	signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
	for {
		select {
		case s := <-sig:
			log.Fatalf("Signal (%d) received, stopping\n", s)
		}
	}
}
Exemple #26
0
func makeTruncatedReply(r *dns.Msg) *dns.Msg {
	// for truncated response, we create a minimal reply with the Truncated bit set
	reply := new(dns.Msg)
	reply.SetReply(r)
	reply.Truncated = true
	return reply
}
// handleDNS is a handler function to actualy perform the dns querey response
func (c *CatchAll) handleDNS(w dns.ResponseWriter, r *dns.Msg) {
	defer w.Close()
	var rr dns.RR

	domainSpoof := r.Question[0].Name

	msgResp := new(dns.Msg)
	msgResp.SetReply(r)
	msgResp.Compress = false

	rr = new(dns.A)

	if c.SpoofDomain {
		rr.(*dns.A).Hdr = dns.RR_Header{Name: domainSpoof, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
	} else {
		rr.(*dns.A).Hdr = dns.RR_Header{Name: c.Domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 0}
	}

	rr.(*dns.A).A = c.IP

	switch r.Question[0].Qtype {
	case dns.TypeA:
		msgResp.Answer = append(msgResp.Answer, rr)
	default:
		log.Warnf("Unknown dns type %T", r.Question[0].Qtype)
		return
	}

	w.WriteMsg(msgResp)
}
Exemple #28
0
func makeDNSFailResponse(r *dns.Msg) *dns.Msg {
	m := new(dns.Msg)
	m.SetReply(r)
	m.RecursionAvailable = true
	m.Rcode = dns.RcodeNameError
	return m
}
Exemple #29
0
func (r *resolver) handlePTRQuery(ptr string, query *dns.Msg) (*dns.Msg, error) {
	parts := []string{}

	if strings.HasSuffix(ptr, ptrIPv4domain) {
		parts = strings.Split(ptr, ptrIPv4domain)
	} else if strings.HasSuffix(ptr, ptrIPv6domain) {
		parts = strings.Split(ptr, ptrIPv6domain)
	} else {
		return nil, fmt.Errorf("invalid PTR query, %v", ptr)
	}

	host := r.backend.ResolveIP(parts[0])

	if len(host) == 0 {
		return nil, nil
	}

	logrus.Debugf("Lookup for IP %s: name %s", parts[0], host)
	fqdn := dns.Fqdn(host)

	resp := new(dns.Msg)
	resp.SetReply(query)
	setCommonFlags(resp)

	rr := new(dns.PTR)
	rr.Hdr = dns.RR_Header{Name: ptr, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: respTTL}
	rr.Ptr = fqdn
	resp.Answer = append(resp.Answer, rr)
	return resp, nil
}
Exemple #30
0
func (c Chaos) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
	state := middleware.State{W: w, Req: r}
	if state.QClass() != dns.ClassCHAOS || state.QType() != dns.TypeTXT {
		return c.Next.ServeDNS(ctx, w, r)
	}

	m := new(dns.Msg)
	m.SetReply(r)

	hdr := dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeTXT, Class: dns.ClassCHAOS, Ttl: 0}
	switch state.Name() {
	default:
		return c.Next.ServeDNS(ctx, w, r)
	case "authors.bind.":
		for a, _ := range c.Authors {
			m.Answer = append(m.Answer, &dns.TXT{Hdr: hdr, Txt: []string{trim(a)}})
		}
	case "version.bind.", "version.server.":
		m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{trim(c.Version)}}}
	case "hostname.bind.", "id.server.":
		hostname, err := os.Hostname()
		if err != nil {
			hostname = "localhost"
		}
		m.Answer = []dns.RR{&dns.TXT{Hdr: hdr, Txt: []string{trim(hostname)}}}
	}
	state.SizeAndDo(m)
	w.WriteMsg(m)
	return 0, nil
}