// An A record is generated when there is only one ZknsAddr, it // has no port component and provides an IPv4 address. func (rz *zknsResolver) getA(qname string) ([]*pdnsReply, error) { if !strings.HasSuffix(qname, rz.zknsDomain) { return nil, fmt.Errorf("invalid domain for query: %v", qname) } if qname[0] == '_' { // Since PDNS probes for all types, use some heuristics to limit error noise. relog.Debug("skipping A query: %v", qname) return nil, nil } zkname := qname[:len(qname)-len(rz.zknsDomain)] nameParts := reverse(strings.Split(zkname, ".")) zkPath := path.Join(rz.zkRoot, path.Join(nameParts...)) addrs, err := zkns.ReadAddrs(rz.zconn, zkPath) if err != nil { return nil, err } if len(addrs.Entries) != 1 || addrs.Entries[0].IPv4 == "" { // Since PDNS probes for all types, this isn't really an error worth mentioning. // return nil, fmt.Errorf("invalid response for CNAME query: %v", qname) return nil, nil } return []*pdnsReply{&pdnsReply{qname, "IN", "A", defaultTTL, defaultId, addrs.Entries[0].IPv4}}, nil }
func (rz *zknsResolver) getSRV(qname string) ([]*pdnsReply, error) { if !strings.HasSuffix(qname, rz.zknsDomain) { return nil, fmt.Errorf("invalid domain for query: %v", qname) } zkname := qname[:len(qname)-len(rz.zknsDomain)] nameParts := strings.Split(zkname, ".") portName := nameParts[0] if portName[0] != '_' { // Since PDNS probes for all types, this isn't really an error worth mentioning. // fmt.Errorf("invalid port name for query: %v", portName) relog.Debug("skipping SRV query: %v", qname) return nil, nil } nameParts = reverse(nameParts[1:]) zkPath := path.Join(rz.zkRoot, path.Join(nameParts...)) addrs, err := zkns.ReadAddrs(rz.zconn, zkPath) if err != nil { return nil, err } replies := make([]*pdnsReply, 0, 16) for _, addr := range addrs.Entries { content := fmt.Sprintf("%v\t%v %v %v", defaultPriority, defaultWeight, addr.NamedPortMap[portName], addr.Host) replies = append(replies, &pdnsReply{qname, "IN", "SRV", defaultTTL, defaultId, content}) } return replies, nil }
// An CNAME record is generated when there is only one ZknsAddr, it // has no port component. Multiple CNAMEs violate DNS protocols despite // support in some versions of BIND. func (rz *zknsResolver) getCNAME(qname string) ([]*pdnsReply, error) { if !strings.HasSuffix(qname, rz.zknsDomain) { return nil, fmt.Errorf("invalid domain for query: %v", qname) } if qname[0] == '_' { // Since PDNS probes for all types, use some heuristics to limit error noise. log.Infof("skipping CNAME query: %v", qname) return nil, nil } zkname := qname[:len(qname)-len(rz.zknsDomain)] nameParts := reverse(strings.Split(zkname, ".")) zkPath := path.Join(rz.zkRoot, path.Join(nameParts...)) addrs, err := zkns.ReadAddrs(rz.zconn, zkPath) if err != nil { return nil, err } if !addrs.IsValidCNAME() { log.Warningf("invalid CNAME record addrs at path %v", zkPath) // Since PDNS probes for all types, this isn't really an error worth propagating. // return nil, fmt.Errorf("invalid response for CNAME query: %v", qname) return nil, nil } return []*pdnsReply{&pdnsReply{qname, "IN", "CNAME", defaultTTL, defaultId, addrs.Entries[0].Host}}, nil }
// An A record is generated when there is only one ZknsAddr, it // has no port component and provides an IPv4 address. // FIXME(msolo) Multiple IP addresses could be handed out. func (rz *zknsResolver) getA(qname string) ([]*pdnsReply, error) { if !strings.HasSuffix(qname, rz.zknsDomain) { return nil, fmt.Errorf("invalid domain for query: %v", qname) } if qname[0] == '_' { // Since PDNS probes for all types, use some heuristics to limit error noise. log.Infof("skipping A query, looks like SRV name: %v", qname) return nil, nil } zkname := qname[:len(qname)-len(rz.zknsDomain)] nameParts := reverse(strings.Split(zkname, ".")) zkPath := path.Join(rz.zkRoot, path.Join(nameParts...)) addrs, err := zkns.ReadAddrs(rz.zconn, zkPath) if err != nil { return nil, err } if !addrs.IsValidA() { log.Warningf("invalid A record addrs at path %v", zkPath) // Since PDNS probes for all types, this isn't really an error worth propagating. // return nil, fmt.Errorf("invalid response for A query: %v", qname) return nil, nil } replies := make([]*pdnsReply, len(addrs.Entries)) for i, entry := range addrs.Entries { replies[i] = &pdnsReply{qname, "IN", "A", defaultTTL, defaultId, entry.IPv4} } // Shuffle replies since that seems like the only reasonable strategy in a // stateless distributed environment. for i := range replies { j := rand.Intn(i + 1) replies[i], replies[j] = replies[j], replies[i] } return replies, nil }