func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) { addr, ipv6Miss := r.sb.ResolveName(name, ipType) if addr == nil && ipv6Miss { // Send a reply without any Answer sections log.Debugf("Lookup name %s present without IPv6 address", name) resp := createRespMsg(query) return resp, nil } if addr == nil { return nil, nil } log.Debugf("Lookup for %s: IP %v", name, addr) resp := createRespMsg(query) if len(addr) > 1 { addr = shuffleAddr(addr) } if ipType == types.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 (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 route(w dns.ResponseWriter, req *dns.Msg) { if len(req.Question) != 1 { failWithRcode(w, req, dns.RcodeRefused) return } question := req.Question[0] qtype := question.Qtype if question.Qclass != dns.ClassINET { failWithRcode(w, req, dns.RcodeRefused) return } remoteIP := w.RemoteAddr().(*net.UDPAddr).IP m := new(dns.Msg) m.Id = req.Id switch qtype { case dns.TypeA: if remoteIP4 := remoteIP.To4(); remoteIP4 != nil { rr := new(dns.A) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.A = remoteIP4 m.Answer = []dns.RR{rr} } case dns.TypeAAAA: if remoteIP16 := remoteIP.To16(); remoteIP16 != nil { rr := new(dns.AAAA) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.AAAA = remoteIP16 m.Answer = []dns.RR{rr} } case dns.TypeTXT: rr := new(dns.TXT) rr.Hdr = dns.RR_Header{Name: question.Name, Rrtype: question.Qtype, Class: dns.ClassINET, Ttl: 10} rr.Txt = []string{fmt.Sprintf("Resolver IP: %v", remoteIP.String())} m.Answer = []dns.RR{rr} } m.Question = req.Question m.Response = true m.Authoritative = true w.WriteMsg(m) }
func parseValue(t uint16, value string, h dns.RR_Header) dns.RR { switch t { case dns.TypeA: a := new(dns.A) a.Hdr = h a.A, _ = parseA(value) return a case dns.TypeAAAA: aaaa := new(dns.AAAA) aaaa.Hdr = h aaaa.AAAA, _ = parseAAAA(value) return aaaa case dns.TypeSRV: srv := new(dns.SRV) srv.Hdr = h srv.Priority, srv.Weight, srv.Port, srv.Target, _ = parseSRV(value) return srv } return nil }
func answerAAAA(q *dns.Question, v *DNSValue) dns.RR { answer := new(dns.AAAA) answer.Header().Name = q.Name answer.Header().Rrtype = dns.TypeAAAA answer.Header().Class = dns.ClassINET answer.AAAA = net.ParseIP(v.Value) return answer }
func (s *server) AddressRecords(q dns.Question) (records []dns.RR, err error) { name := strings.ToLower(q.Name) if name == "master."+s.config.Domain || name == s.config.Domain { for _, m := range s.client.GetCluster() { u, e := url.Parse(m) if e != nil { continue } h, _, e := net.SplitHostPort(u.Host) if e != nil { continue } ip := net.ParseIP(h) switch { case ip.To4() != nil && q.Qtype == dns.TypeA: records = append(records, &dns.A{Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: s.Ttl}, A: ip.To4()}) case ip.To4() == nil && q.Qtype == dns.TypeAAAA: records = append(records, &dns.AAAA{Hdr: dns.RR_Header{Name: q.Name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: s.Ttl}, AAAA: ip.To16()}) } } return } r, err := s.client.Get(path(name), false, true) if err != nil { println(err.Error()) return nil, err } var serv *Service if !r.Node.Dir { // single element if err := json.Unmarshal([]byte(r.Node.Value), &serv); err != nil { log.Printf("error: Failure to parse value: %q", err) return nil, err } ip := net.ParseIP(serv.Host) ttl := uint32(r.Node.TTL) if ttl == 0 { ttl = s.Ttl } switch { case ip == nil: case ip.To4() != nil && q.Qtype == dns.TypeA: a := new(dns.A) a.Hdr = dns.RR_Header{Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: ttl} a.A = ip.To4() records = append(records, a) case ip.To4() == nil && q.Qtype == dns.TypeAAAA: aaaa := new(dns.AAAA) aaaa.Hdr = dns.RR_Header{Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: ttl} aaaa.AAAA = ip.To16() records = append(records, aaaa) } return records, nil } for _, serv := range s.loopNodes(&r.Node.Nodes) { ip := net.ParseIP(serv.Host) switch { case ip == nil: case ip.To4() != nil && q.Qtype == dns.TypeA: a := new(dns.A) a.Hdr = dns.RR_Header{Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: uint32(r.Node.TTL)} a.A = ip.To4() records = append(records, a) case ip.To4() == nil && q.Qtype == dns.TypeAAAA: aaaa := new(dns.AAAA) aaaa.Hdr = dns.RR_Header{Name: q.Name, Rrtype: q.Qtype, Class: dns.ClassINET, Ttl: uint32(r.Node.TTL)} aaaa.AAAA = ip.To16() records = append(records, aaaa) } } if s.config.RoundRobin { switch l := len(records); l { case 2: if dns.Id()%2 == 0 { records[0], records[1] = records[1], records[0] } default: // Do a minimum of l swap, maximum of 4l swaps for j := 0; j < l*(int(dns.Id())%4+1); j++ { q := int(dns.Id()) % l p := int(dns.Id()) % l if q == p { p = (p + 1) % l } records[q], records[p] = records[p], records[q] } } } return records, nil }
// 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.stats { s.counts.mtx.RLock() log.Printf("%s - DNS available: v4std: %v v4non: %v v6std: %v v6non: %v\n", s.name, len(rr4std), len(rr4non), len(rr6std), len(rr6non)) log.Printf("%s - DNS counts: v4std: %v v4non: %v v6std: %v v6non: %v total: %v\n", s.name, s.counts.DNSCounts[dnsV4Std], s.counts.DNSCounts[dnsV4Non], s.counts.DNSCounts[dnsV6Std], s.counts.DNSCounts[dnsV6Non], s.counts.DNSCounts[dnsV4Std]+s.counts.DNSCounts[dnsV4Non]+s.counts.DNSCounts[dnsV6Std]+s.counts.DNSCounts[dnsV6Non]) s.counts.mtx.RUnlock() } }