package external import ( "github.com/coredns/coredns/plugin/pkg/dnsutil" "github.com/coredns/coredns/request" "github.com/miekg/dns" ) // serveApex serves request that hit the zone' apex. A reply is written back to the client. func (e *External) serveApex(state request.Request) (int, error) { m := new(dns.Msg) m.SetReply(state.Req) m.Authoritative = true switch state.QType() { case dns.TypeSOA: m.Answer = []dns.RR{e.soa(state)} case dns.TypeNS: m.Answer = []dns.RR{e.ns(state)} addr := e.externalAddrFunc(state, e.headless) for _, rr := range addr { rr.Header().Ttl = e.ttl rr.Header().Name = dnsutil.Join("ns1", e.apex, state.QName()) m.Extra = append(m.Extra, rr) } default: m.Ns = []dns.RR{e.soa(state)} } state.W.WriteMsg(m) return 0, nil } // serveSubApex serves requests that hit the zones fake 'dns' subdomain where our nameservers live. func (e *External) serveSubApex(state request.Request) (int, error) { base, _ := dnsutil.TrimZone(state.Name(), state.Zone) m := new(dns.Msg) m.SetReply(state.Req) m.Authoritative = true // base is either dns. of ns1.dns (or another name), if it's longer return nxdomain switch labels := dns.CountLabel(base); labels { default: m.SetRcode(m, dns.RcodeNameError) m.Ns = []dns.RR{e.soa(state)} state.W.WriteMsg(m) return 0, nil case 2: nl, _ := dns.NextLabel(base, 0) ns := base[:nl] if ns != "ns1." { // nxdomain m.SetRcode(m, dns.RcodeNameError) m.Ns = []dns.RR{e.soa(state)} state.W.WriteMsg(m) return 0, nil } addr := e.externalAddrFunc(state, e.headless) for _, rr := range addr { rr.Header().Ttl = e.ttl rr.Header().Name = state.QName() switch state.QType() { case dns.TypeA: if rr.Header().Rrtype == dns.TypeA { m.Answer = append(m.Answer, rr) } case dns.TypeAAAA: if rr.Header().Rrtype == dns.TypeAAAA { m.Answer = append(m.Answer, rr) } } } if len(m.Answer) == 0 { m.Ns = []dns.RR{e.soa(state)} } state.W.WriteMsg(m) return 0, nil case 1: // nodata for the dns empty non-terminal m.Ns = []dns.RR{e.soa(state)} state.W.WriteMsg(m) return 0, nil } } func (e *External) soa(state request.Request) *dns.SOA { header := dns.RR_Header{Name: state.Zone, Rrtype: dns.TypeSOA, Ttl: e.ttl, Class: dns.ClassINET} soa := &dns.SOA{Hdr: header, Mbox: dnsutil.Join(e.hostmaster, e.apex, state.Zone), Ns: dnsutil.Join("ns1", e.apex, state.Zone), Serial: e.externalSerialFunc(state.Zone), Refresh: 7200, Retry: 1800, Expire: 86400, Minttl: e.ttl, } return soa } func (e *External) ns(state request.Request) *dns.NS { header := dns.RR_Header{Name: state.Zone, Rrtype: dns.TypeNS, Ttl: e.ttl, Class: dns.ClassINET} ns := &dns.NS{Hdr: header, Ns: dnsutil.Join("ns1", e.apex, state.Zone)} return ns }