mirror of
				https://github.com/coredns/coredns.git
				synced 2025-11-04 03:03:14 -05:00 
			
		
		
		
	
		
			
	
	
		
			98 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			98 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| 
								 | 
							
								package external
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								import (
							 | 
						||
| 
								 | 
							
									"context"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/coredns/coredns/plugin"
							 | 
						||
| 
								 | 
							
									"github.com/coredns/coredns/plugin/etcd/msg"
							 | 
						||
| 
								 | 
							
									"github.com/coredns/coredns/plugin/transfer"
							 | 
						||
| 
								 | 
							
									"github.com/coredns/coredns/request"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									"github.com/miekg/dns"
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// Transfer implements transfer.Transferer
							 | 
						||
| 
								 | 
							
								func (e *External) Transfer(zone string, serial uint32) (<-chan []dns.RR, error) {
							 | 
						||
| 
								 | 
							
									z := plugin.Zones(e.Zones).Matches(zone)
							 | 
						||
| 
								 | 
							
									if z != zone {
							 | 
						||
| 
								 | 
							
										return nil, transfer.ErrNotAuthoritative
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									ctx := context.Background()
							 | 
						||
| 
								 | 
							
									ch := make(chan []dns.RR, 2)
							 | 
						||
| 
								 | 
							
									if zone == "." {
							 | 
						||
| 
								 | 
							
										zone = ""
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									state := request.Request{Zone: zone}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// SOA
							 | 
						||
| 
								 | 
							
									soa := e.soa(state)
							 | 
						||
| 
								 | 
							
									ch <- []dns.RR{soa}
							 | 
						||
| 
								 | 
							
									if serial != 0 && serial >= soa.Serial {
							 | 
						||
| 
								 | 
							
										close(ch)
							 | 
						||
| 
								 | 
							
										return ch, nil
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									go func() {
							 | 
						||
| 
								 | 
							
										// Add NS
							 | 
						||
| 
								 | 
							
										nsName := "ns1." + e.apex + "." + zone
							 | 
						||
| 
								 | 
							
										nsHdr := dns.RR_Header{Name: zone, Rrtype: dns.TypeNS, Ttl: e.ttl, Class: dns.ClassINET}
							 | 
						||
| 
								 | 
							
										ch <- []dns.RR{&dns.NS{Hdr: nsHdr, Ns: nsName}}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										// Add Nameserver A/AAAA records
							 | 
						||
| 
								 | 
							
										nsRecords := e.externalAddrFunc(state)
							 | 
						||
| 
								 | 
							
										for i := range nsRecords {
							 | 
						||
| 
								 | 
							
											// externalAddrFunc returns incomplete header names, correct here
							 | 
						||
| 
								 | 
							
											nsRecords[i].Header().Name = nsName
							 | 
						||
| 
								 | 
							
											nsRecords[i].Header().Ttl = e.ttl
							 | 
						||
| 
								 | 
							
											ch <- []dns.RR{nsRecords[i]}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										svcs := e.externalServicesFunc(zone)
							 | 
						||
| 
								 | 
							
										srvSeen := make(map[string]struct{})
							 | 
						||
| 
								 | 
							
										for i := range svcs {
							 | 
						||
| 
								 | 
							
											name := msg.Domain(svcs[i].Key)
							 | 
						||
| 
								 | 
							
											if svcs[i].TargetStrip == 0 {
							 | 
						||
| 
								 | 
							
												// Add Service A/AAAA records
							 | 
						||
| 
								 | 
							
												s := request.Request{Req: &dns.Msg{Question: []dns.Question{{Name: name}}}}
							 | 
						||
| 
								 | 
							
												as := e.a(ctx, []msg.Service{svcs[i]}, s)
							 | 
						||
| 
								 | 
							
												if len(as) > 0 {
							 | 
						||
| 
								 | 
							
													ch <- as
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												aaaas := e.aaaa(ctx, []msg.Service{svcs[i]}, s)
							 | 
						||
| 
								 | 
							
												if len(aaaas) > 0 {
							 | 
						||
| 
								 | 
							
													ch <- aaaas
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												// Add bare SRV record, ensuring uniqueness
							 | 
						||
| 
								 | 
							
												recs, _ := e.srv(ctx, []msg.Service{svcs[i]}, s)
							 | 
						||
| 
								 | 
							
												for _, srv := range recs {
							 | 
						||
| 
								 | 
							
													if !nameSeen(srvSeen, srv) {
							 | 
						||
| 
								 | 
							
														ch <- []dns.RR{srv}
							 | 
						||
| 
								 | 
							
													}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
												continue
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
											// Add full SRV record, ensuring uniqueness
							 | 
						||
| 
								 | 
							
											s := request.Request{Req: &dns.Msg{Question: []dns.Question{{Name: name}}}}
							 | 
						||
| 
								 | 
							
											recs, _ := e.srv(ctx, []msg.Service{svcs[i]}, s)
							 | 
						||
| 
								 | 
							
											for _, srv := range recs {
							 | 
						||
| 
								 | 
							
												if !nameSeen(srvSeen, srv) {
							 | 
						||
| 
								 | 
							
													ch <- []dns.RR{srv}
							 | 
						||
| 
								 | 
							
												}
							 | 
						||
| 
								 | 
							
											}
							 | 
						||
| 
								 | 
							
										}
							 | 
						||
| 
								 | 
							
										ch <- []dns.RR{soa}
							 | 
						||
| 
								 | 
							
										close(ch)
							 | 
						||
| 
								 | 
							
									}()
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									return ch, nil
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								func nameSeen(namesSeen map[string]struct{}, rr dns.RR) bool {
							 | 
						||
| 
								 | 
							
									if _, duplicate := namesSeen[rr.Header().Name]; duplicate {
							 | 
						||
| 
								 | 
							
										return true
							 | 
						||
| 
								 | 
							
									}
							 | 
						||
| 
								 | 
							
									namesSeen[rr.Header().Name] = struct{}{}
							 | 
						||
| 
								 | 
							
									return false
							 | 
						||
| 
								 | 
							
								}
							 |