func get_serial(zone_name, query_dest string) (uint32, error) { var in *dns.Msg m := new(dns.Msg) m.SetQuestion(zone_name, dns.TypeSOA) if conf.Transfer_source != nil { d := net.Dialer{LocalAddr: conf.Transfer_source} c, err := d.Dial("tcp", query_dest) if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem dialing query_dest %s", query_dest)) return 0, err } co := &dns.Conn{Conn: c} co.WriteMsg(m) in, err = co.ReadMsg() if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem querying query_dest %s", query_dest)) return 0, err } co.Close() } else { c := &dns.Client{DialTimeout: conf.Query_timeout, ReadTimeout: conf.Query_timeout} if conf.All_tcp == true { c.Net = "tcp" } // _ is query time, might be useful later var err error in, _, err = c.Exchange(m, query_dest) if err != nil { logger.Error(fmt.Sprintf("QUERY ERROR : problem querying query_dest %s", query_dest)) return 0, err } } return serial_query_parse(in), nil }
func (res *Resolver) handleSRV(rs *records.RecordGenerator, name string, m, r *dns.Msg) error { var errs multiError added := map[string]struct{}{} // track the A RR's we've already added, avoid dups for srv := range rs.SRVs[name] { srvRR, err := res.formatSRV(r.Question[0].Name, srv) if err != nil { errs.Add(err) continue } m.Answer = append(m.Answer, srvRR) host := strings.Split(srv, ":")[0] if _, found := added[host]; found { // avoid dups continue } if len(rs.As[host]) == 0 { continue } if a, ok := rs.As.First(host); ok { aRR, err := res.formatA(host, a) if err != nil { errs.Add(err) continue } m.Extra = append(m.Extra, aRR) added[host] = struct{}{} } } return errs }
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 }
// 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) }
// Perform DNS resolution func resolve(w http.ResponseWriter, r *http.Request, server string, domain string, querytype uint16) { m := new(dns.Msg) m.SetQuestion(domain, querytype) m.MsgHdr.RecursionDesired = true w.Header().Set("Content-Type", "application/json") w.Header().Set("Access-Control-Allow-Origin", "*") c := new(dns.Client) Redo: if in, _, err := c.Exchange(m, server); err == nil { // Second return value is RTT, not used for now if in.MsgHdr.Truncated { c.Net = "tcp" goto Redo } switch in.MsgHdr.Rcode { case dns.RcodeServerFailure: error(w, 500, 502, "The name server encountered an internal failure while processing this request (SERVFAIL)") case dns.RcodeNameError: error(w, 500, 503, "Some name that ought to exist, does not exist (NXDOMAIN)") case dns.RcodeRefused: error(w, 500, 505, "The name server refuses to perform the specified operation for policy or security reasons (REFUSED)") default: jsonify(w, r, in.Question, in.Answer, in.Ns, in.Extra) } } else { error(w, 500, 501, "DNS server could not be reached") } }
func TestDNS_CaseInsensitiveNodeLookup(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() testutil.WaitForLeader(t, srv.agent.RPC, "dc1") // Register node args := &structs.RegisterRequest{ Datacenter: "dc1", Node: "Foo", Address: "127.0.0.1", } var out struct{} if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { t.Fatalf("err: %v", err) } m := new(dns.Msg) m.SetQuestion("fOO.node.dc1.consul.", dns.TypeANY) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) != 1 { t.Fatalf("empty lookup: %#v", in) } }
func TestDNS_Recurse(t *testing.T) { recursor := makeRecursor(t, []dns.RR{dnsA("apple.com", "1.2.3.4")}) defer recursor.Shutdown() dir, srv := makeDNSServerConfig(t, func(c *Config) { c.DNSRecursor = recursor.Addr }, nil) defer os.RemoveAll(dir) defer srv.agent.Shutdown() m := new(dns.Msg) m.SetQuestion("apple.com.", dns.TypeANY) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) == 0 { t.Fatalf("Bad: %#v", in) } if in.Rcode != dns.RcodeSuccess { t.Fatalf("Bad: %#v", in) } }
func TestMsgOverflow(t *testing.T) { if testing.Short() { t.Skip("skipping test in short mode.") } s := newTestServer(t, false) defer s.Stop() c := new(dns.Client) m := new(dns.Msg) // TODO(miek): rethink how to enable metrics in tests. if !metricsDone { Metrics() } for i := 0; i < 2000; i++ { is := strconv.Itoa(i) m := &msg.Service{ Host: "2001::" + is, Key: "machine" + is + ".machines.skydns.test.", } addService(t, s, m.Key, 0, m) defer delService(t, s, m.Key) } m.SetQuestion("machines.skydns.test.", dns.TypeSRV) resp, _, err := c.Exchange(m, "127.0.0.1:"+StrPort) if err != nil { t.Fatal(err) } t.Logf("%s", resp) if resp.Rcode != dns.RcodeServerFailure { t.Fatalf("expecting server failure, got %d", resp.Rcode) } }
func (s *DNSServer) handlePTRRequest(r *dns.Msg, m *dns.Msg) { m.Answer = make([]dns.RR, 0, 2) query := r.Question[0].Name if query[len(query)-1] == '.' { query = query[:len(query)-1] } for service := range s.queryIp(query) { var ttl int if service.Ttl != -1 { ttl = service.Ttl } else { ttl = s.config.ttl } for domain := range s.listDomains(service) { rr := new(dns.PTR) rr.Hdr = dns.RR_Header{ Name: r.Question[0].Name, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: uint32(ttl), } rr.Ptr = domain m.Answer = append(m.Answer, rr) } } }
func ParseDnsFrame(f Frame, req *dns.Msg) (addrs []net.IP, err error) { ft, ok := f.(*FrameDns) if !ok { return nil, ErrDnsMsgIllegal } res := new(dns.Msg) err = res.Unpack(ft.Data) if err != nil || !res.Response || res.Id != req.Id { return nil, ErrDnsMsgIllegal } if DEBUGDNS { DebugDNS(res, req.Question[0].Name) } for _, a := range res.Answer { switch ta := a.(type) { case *dns.A: addrs = append(addrs, ta.A) case *dns.AAAA: addrs = append(addrs, ta.AAAA) } } return }
func TestShuffleAnswers(t *testing.T) { var res Resolver m := new(dns.Msg) for i := 0; i < 10; i++ { name := "10.0.0." + strconv.Itoa(i) rr, err := res.formatA("blah.com", name) if err != nil { t.Error(err) } m.Answer = append(m.Answer, rr) } n := new(dns.Msg) c := make([]dns.RR, len(m.Answer)) copy(c, m.Answer) n.Answer = c _ = shuffleAnswers(m.Answer) sflag := false // 10! chance of failing here for i := 0; i < 10; i++ { if n.Answer[i] != m.Answer[i] { sflag = true break } } if !sflag { t.Error("not shuffling") } }
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) }
// 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 }
func (p *Parser) handleExplanation() string { resolvedDomain, err := ParseMacroToken(p, p.Explanation) if err != nil || isEmpty(&resolvedDomain) { // TODO(zaccone): Should we return some internal error return "" } resolvedDomain = NormalizeHost(resolvedDomain) query := new(dns.Msg) query.SetQuestion(resolvedDomain, dns.TypeTXT) c := new(dns.Client) response, _, err := c.Exchange(query, Nameserver) if err != nil || (response != nil && response.Rcode != dns.RcodeSuccess) { return "" } explanation := make([]string, 0, len(response.Answer)) for _, answer := range response.Answer { if q, ok := answer.(*dns.TXT); ok { for _, txt := range q.Txt { explanation = append(explanation, txt) } } } // RFC 7208, section 6.2 specifies that result string should be // concatenated with no spaces. parsedExplanation, err := ParseMacro(p, strings.Join(explanation, "")) if err != nil { return "" } return parsedExplanation }
// Check that we can prune an answer func TestPrune(t *testing.T) { InitDefaultLogging(testing.Verbose()) Info.Println("TestPrune starting") questionMsg := new(dns.Msg) questionMsg.SetQuestion("name", dns.TypeA) questionMsg.RecursionDesired = true question := &questionMsg.Question[0] records := []ZoneRecord{ Record{"name", net.ParseIP("10.0.1.1"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.2"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.3"), 0, 0, 0}, Record{"name", net.ParseIP("10.0.1.4"), 0, 0, 0}, } reply := makeAddressReply(questionMsg, question, records, DefaultLocalTTL) reply.Answer[0].Header().Ttl = DefaultLocalTTL pruned := pruneAnswers(reply.Answer, 1) require.Equal(t, 1, len(pruned), "wrong number of answers") pruned = pruneAnswers(reply.Answer, 2) require.Equal(t, 2, len(pruned), "wrong number of answers") pruned = pruneAnswers(reply.Answer, 0) require.Equal(t, len(records), len(pruned), "wrong number of answers") }
func (s *DNSServer) handleARequest(r *dns.Msg, m *dns.Msg) { m.Answer = make([]dns.RR, 0, 2) query := r.Question[0].Name if query[len(query)-1] == '.' { query = query[:len(query)-1] } for service := range s.queryServices(query) { rr := new(dns.A) var ttl int if service.Ttl != -1 { ttl = service.Ttl } else { ttl = s.config.ttl } rr.Hdr = dns.RR_Header{ Name: r.Question[0].Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: uint32(ttl), } rr.A = service.Ip m.Answer = append(m.Answer, rr) } }
func TestDNS_NonExistingLookup(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) // lookup a non-existing node, we should receive a SOA m := new(dns.Msg) m.SetQuestion("nonexisting.consul.", dns.TypeANY) c := new(dns.Client) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Ns) != 1 { t.Fatalf("Bad: %#v %#v", in, len(in.Answer)) } soaRec, ok := in.Ns[0].(*dns.SOA) if !ok { t.Fatalf("Bad: %#v", in.Ns[0]) } if soaRec.Hdr.Ttl != 0 { t.Fatalf("Bad: %#v", in.Ns[0]) } }
func main() { if len(os.Args) != 2 { fmt.Printf("%s NAMESERVER\n", os.Args[0]) os.Exit(1) } conf, _ := dns.ClientConfigFromFile("/etc/resolv.conf") m := new(dns.Msg) m.Question = make([]dns.Question, 1) c := new(dns.Client) addr := addresses(conf, c, os.Args[1]) if len(addr) == 0 { fmt.Printf("No address found for %s\n", os.Args[1]) os.Exit(1) } for _, a := range addr { m.Question[0] = dns.Question{"version.bind.", dns.TypeTXT, dns.ClassCHAOS} in, rtt, _ := c.ExchangeRtt(m, a) if in != nil && len(in.Answer) > 0 { fmt.Printf("(time %.3d µs) %v\n", rtt/1e3, in.Answer[0]) } m.Question[0] = dns.Question{"hostname.bind.", dns.TypeTXT, dns.ClassCHAOS} in, rtt, _ = c.ExchangeRtt(m, a) if in != nil && len(in.Answer) > 0 { fmt.Printf("(time %.3d µs) %v\n", rtt/1e3, in.Answer[0]) } } }
func TestDNS_ServiceLookup_TagPeriod(t *testing.T) { dir, srv := makeDNSServer(t) defer os.RemoveAll(dir) defer srv.agent.Shutdown() testutil.WaitForLeader(t, srv.agent.RPC, "dc1") // Register node args := &structs.RegisterRequest{ Datacenter: "dc1", Node: "foo", Address: "127.0.0.1", Service: &structs.NodeService{ Service: "db", Tags: []string{"v1.master"}, Port: 12345, }, } var out struct{} if err := srv.agent.RPC("Catalog.Register", args, &out); err != nil { t.Fatalf("err: %v", err) } m := new(dns.Msg) m.SetQuestion("v1.master.db.service.consul.", dns.TypeSRV) c := new(dns.Client) addr, _ := srv.agent.config.ClientListener("", srv.agent.config.Ports.DNS) in, _, err := c.Exchange(m, addr.String()) if err != nil { t.Fatalf("err: %v", err) } if len(in.Answer) != 1 { t.Fatalf("Bad: %#v", in) } srvRec, ok := in.Answer[0].(*dns.SRV) if !ok { t.Fatalf("Bad: %#v", in.Answer[0]) } if srvRec.Port != 12345 { t.Fatalf("Bad: %#v", srvRec) } if srvRec.Target != "foo.node.dc1.consul." { t.Fatalf("Bad: %#v", srvRec) } aRec, ok := in.Extra[0].(*dns.A) if !ok { t.Fatalf("Bad: %#v", in.Extra[0]) } if aRec.Hdr.Name != "foo.node.dc1.consul." { t.Fatalf("Bad: %#v", in.Extra[0]) } if aRec.A.String() != "127.0.0.1" { t.Fatalf("Bad: %#v", in.Extra[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) } }
func TestTCP(t *testing.T) { handle, err := pcap.OpenOffline("tcptest.pcap") if err != nil { panic(err) } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) defer handle.Close() tcpPack := make(chan gopacket.Packet, 10) nomalPack := make(chan gopacket.Packet, 5) for input_pack := range packetSource.Packets() { // send tcp package for channel tcpLayer := input_pack.Layer(layers.LayerTypeTCP) if tcpLayer != nil { tcpPack <- input_pack // send packet to tcp ASSEMBLER } } streamFactory := &DNSStreamFactory{normal: nomalPack} streamPool := tcpassembly.NewStreamPool(streamFactory) assembler := tcpassembly.NewAssembler(streamPool) go tcpAssemble(tcpPack, assembler) pack := <-nomalPack udpLayer := pack.Layer(layers.LayerTypeUDP) if udpLayer == nil { t.Errorf("can not fine udp Layer in result") } dns_message := new(dns.Msg) err = dns_message.Unpack(udpLayer.LayerPayload()) if err != nil { t.Errorf("can not parse dns message") } fmt.Printf(dns_message.String()) }
// resolveCNAME is used to recursively resolve CNAME records func (d *DNSServer) resolveCNAME(name string) []dns.RR { // Do nothing if we don't have a recursor if len(d.recursors) == 0 { return nil } // Ask for any A records m := new(dns.Msg) m.SetQuestion(name, dns.TypeA) // Make a DNS lookup request c := &dns.Client{Net: "udp"} var r *dns.Msg var rtt time.Duration var err error for _, recursor := range d.recursors { r, rtt, err = c.Exchange(m, recursor) if err == nil { d.logger.Printf("[DEBUG] dns: cname recurse RTT for %v (%v)", name, rtt) return r.Answer } d.logger.Printf("[ERR] dns: cname recurse failed for %v: %v", name, err) } d.logger.Printf("[ERR] dns: all resolvers failed for %v", name) return nil }
/* Get a domain's IPs from a specific name server. Parameters: domain the domain you want to query nameserver name server's IP address port 53 in general net tcp or udp timeout in seconds, can be omitted Here's an example: r, e := ARecords("www.example.com", "8.8.8.8", 53, "tcp") if e != nil { fmt.Println(e) } else { fmt.Println(r) } */ func ARecords(domain, nameserver string, port uint16, net string, timeout ...uint8) ([]string, error) { var result []string if net != "tcp" && net != "udp" { return result, errors.New("The parameter 'net' should only be 'tcp' or 'udp'.") } msg := new(mdns.Msg) msg.SetQuestion(mdns.Fqdn(domain), mdns.TypeA) var client *mdns.Client if len(timeout) > 0 { tm := time.Duration(timeout[0]) * time.Second client = &mdns.Client{Net: net, DialTimeout: tm, ReadTimeout: tm, WriteTimeout: tm} } else { client = &mdns.Client{Net: net} } r, _, err := client.Exchange(msg, fmt.Sprintf("%s:%d", nameserver, port)) if err != nil { return result, err } for _, i := range r.Answer { if t, ok := i.(*mdns.A); ok { result = append(result, t.A.String()) } } return result, nil }
func (self *TrivialDnsServer) redirectQuery(w dns.ResponseWriter, r *dns.Msg, newName string) { self.Count("redirected_requests") if !strings.HasSuffix(newName, ".") { newName = newName + "." } newR := new(dns.Msg) newR.SetQuestion(dns.Fqdn(newName), dns.TypeA) if response, _, err := self.exchangeWithUpstream(newR); err == nil { ip := self.getSingleSimpleAnswer(response) if ip == nil { debug("%s redirect to %s yielded no answer", w.RemoteAddr(), newName) self.Count("redirected_nowhere") self.refuse(w, r) return } self.Count("redirected_successively") self.respondSuccessively(w, r, *ip) } else { self.Count("upstream_errors") self.refuse(w, r) log.Printf("%s: error: %s", w.RemoteAddr(), err) } }
func (c *Client) lookupIPs(host string) (ips []net.IP, err error) { m := new(dns.Msg) for _, resolver := range c.Resolvers { m.SetQuestion(dns.Fqdn(host), dns.TypeA) if in, err := dns.Exchange(m, resolver); err == nil { for _, rr := range in.Answer { if a, ok := rr.(*dns.A); ok { ips = append(ips, a.A) } } } else { log.Debug(err) } m.SetQuestion(dns.Fqdn(host), dns.TypeAAAA) if in, err := dns.Exchange(m, resolver); err == nil { for _, rr := range in.Answer { if aaaa, ok := rr.(*dns.AAAA); ok { ips = append(ips, aaaa.AAAA) } } } else { log.Debug(err) } } if len(ips) != 0 { return ips, nil } return net.LookupIP(host) }
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) } } }
func createRespMsg(query *dns.Msg) *dns.Msg { resp := new(dns.Msg) resp.SetReply(query) setCommonFlags(resp) return resp }
// serviceARecords is used to add the SRV records for a service lookup func (d *DNSServer) serviceSRVRecords(dc string, nodes structs.CheckServiceNodes, req, resp *dns.Msg, ttl time.Duration) { handled := make(map[string]struct{}) for _, node := range nodes { // Avoid duplicate entries, possible if a node has // the same service the same port, etc. tuple := fmt.Sprintf("%s:%d", node.Node.Node, node.Service.Port) if _, ok := handled[tuple]; ok { continue } handled[tuple] = struct{}{} // Add the SRV record srvRec := &dns.SRV{ Hdr: dns.RR_Header{ Name: req.Question[0].Name, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: uint32(ttl / time.Second), }, Priority: 1, Weight: 1, Port: uint16(node.Service.Port), Target: fmt.Sprintf("%s.node.%s.%s", node.Node.Node, dc, d.domain), } resp.Answer = append(resp.Answer, srvRec) // Add the extra record records := d.formatNodeRecord(&node.Node, srvRec.Target, dns.TypeANY, ttl) if records != nil { resp.Extra = append(resp.Extra, records...) } } }
func (s *Server) composeBrowsingAnswers(resp *dns.Msg, ttl uint32) { ptr := &dns.PTR{ Hdr: dns.RR_Header{ Name: s.service.ServiceName(), Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: ttl, }, Ptr: s.service.ServiceInstanceName(), } resp.Answer = append(resp.Answer, ptr) txt := &dns.TXT{ Hdr: dns.RR_Header{ Name: s.service.ServiceInstanceName(), Rrtype: dns.TypeTXT, Class: dns.ClassINET, Ttl: ttl, }, Txt: s.service.Text, } srv := &dns.SRV{ Hdr: dns.RR_Header{ Name: s.service.ServiceInstanceName(), Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: ttl, }, Priority: 0, Weight: 0, Port: uint16(s.service.Port), Target: s.service.HostName, } resp.Extra = append(resp.Extra, srv, txt) if s.service.AddrIPv4 != nil { a := &dns.A{ Hdr: dns.RR_Header{ Name: s.service.HostName, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl, }, A: s.service.AddrIPv4, } resp.Extra = append(resp.Extra, a) } if s.service.AddrIPv6 != nil { aaaa := &dns.AAAA{ Hdr: dns.RR_Header{ Name: s.service.HostName, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl, }, AAAA: s.service.AddrIPv6, } resp.Extra = append(resp.Extra, aaaa) } }
func do_axfr(zone_name string) ([]dns.RR, error) { result := []dns.RR{} message := new(dns.Msg) message.SetAxfr(zone_name) transfer := &dns.Transfer{DialTimeout: conf.Query_timeout, ReadTimeout: conf.Query_timeout} if conf.Transfer_source != nil { d := net.Dialer{LocalAddr: conf.Transfer_source} c, err := d.Dial("tcp", conf.Master) if err != nil { logger.Debug("AXFR ERROR : problem dialing master") return result, err } dnscon := &dns.Conn{Conn: c} transfer = &dns.Transfer{Conn: dnscon, DialTimeout: conf.Query_timeout, ReadTimeout: conf.Query_timeout} } channel, err := transfer.In(message, conf.Master) if err != nil { return result, err } for envelope := range channel { result = append(result, envelope.RR...) } return result, nil }