package main import ( "log" // "sync" "github.com/miekg/dns" ) // updateDNS updates the current slices of dns.RR so incoming requests get a // fast answer func updateDNS(s *dnsseeder) { var rr4std, rr4non, rr6std, rr6non []dns.RR s.mtx.RLock() // loop over each dns recprd type we need for t := range []int{dnsV4Std, dnsV4Non, dnsV6Std, dnsV6Non} { // FIXME above needs to be convertwd into one scan of theList if possible numRR := 0 for _, nd := range s.theList { // when we reach max exit if numRR >= 25 { break } if nd.status != statusCG { continue } if t == dnsV4Std || t == dnsV4Non { if t == dnsV4Std && nd.dnsType == dnsV4Std { r := new(dns.A) r.Hdr = dns.RR_Header{Name: s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} r.A = nd.na.IP rr4std = append(rr4std, r) numRR++ } // if the node is using a non standard port then add the encoded port info to DNS if t == dnsV4Non && nd.dnsType == dnsV4Non { r := new(dns.A) r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} r.A = nd.na.IP rr4non = append(rr4non, r) numRR++ r = new(dns.A) r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.ttl} r.A = nd.nonstdIP rr4non = append(rr4non, r) numRR++ } } if t == dnsV6Std || t == dnsV6Non { if t == dnsV6Std && nd.dnsType == dnsV6Std { r := new(dns.AAAA) r.Hdr = dns.RR_Header{Name: s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} r.AAAA = nd.na.IP rr6std = append(rr6std, r) numRR++ } // if the node is using a non standard port then add the encoded port info to DNS if t == dnsV6Non && nd.dnsType == dnsV6Non { r := new(dns.AAAA) r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} r.AAAA = nd.na.IP rr6non = append(rr6non, r) numRR++ r = new(dns.AAAA) r.Hdr = dns.RR_Header{Name: "nonstd." + s.dnsHost + ".", Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.ttl} r.AAAA = nd.nonstdIP rr6non = append(rr6non, r) numRR++ } } } } s.mtx.RUnlock() config.dnsmtx.Lock() // update the map holding the details for this seeder for t := range []int{dnsV4Std, dnsV4Non, dnsV6Std, dnsV6Non} { switch t { case dnsV4Std: config.dns[s.dnsHost+".A"] = rr4std case dnsV4Non: config.dns["nonstd."+s.dnsHost+".A"] = rr4non case dnsV6Std: config.dns[s.dnsHost+".AAAA"] = rr6std case dnsV6Non: config.dns["nonstd."+s.dnsHost+".AAAA"] = rr6non } } config.dnsmtx.Unlock() if config.debug { log.Printf("debug - DNS update complete - rr4std: %v rr4non: %v rr6std: %v rr6non: %v\n", len(rr4std), len(rr4non), len(rr6std), len(rr6non)) } } // handleDNS processes a DNS request from remote client and returns // a list of current ip addresses that the crawlers consider current. func handleDNS(w dns.ResponseWriter, r *dns.Msg) { m := &dns.Msg{MsgHdr: dns.MsgHdr{ Authoritative: true, RecursionAvailable: false, }} m.SetReply(r) var qtype string switch r.Question[0].Qtype { case dns.TypeA: qtype = "A" case dns.TypeAAAA: qtype = "AAAA" case dns.TypeTXT: qtype = "TXT" case dns.TypeMX: qtype = "MX" case dns.TypeNS: qtype = "NS" default: qtype = "UNKNOWN" } config.dnsmtx.RLock() // if the dns map does not have a key for the request it will return an empty slice m.Answer = config.dns[r.Question[0].Name+qtype] config.dnsmtx.RUnlock() w.WriteMsg(m) if config.debug { log.Printf("debug - DNS response Type: standard To IP: %s Query Type: %s\n", w.RemoteAddr().String(), qtype) } // update the stats in a goroutine go updateDNSCounts(r.Question[0].Name, qtype) } // serve starts the requested DNS server listening on the requested port func serve(net, port string) { server := &dns.Server{Addr: ":" + port, Net: net, TsigSecret: nil} if err := server.ListenAndServe(); err != nil { log.Printf("Failed to setup the "+net+" server: %v\n", err) } } /* */