| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | package reverse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"net" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	"github.com/coredns/coredns/plugin" | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/pkg/dnsutil" | 
					
						
							| 
									
										
										
										
											2017-02-21 22:51:47 -08:00
										 |  |  | 	"github.com/coredns/coredns/request" | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns" | 
					
						
							|  |  |  | 	"golang.org/x/net/context" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | // Reverse provides dynamic reverse DNS and the related forward RR. | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | type Reverse struct { | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 	Next        plugin.Handler | 
					
						
							| 
									
										
										
										
											2017-02-20 21:00:00 +00:00
										 |  |  | 	Networks    networks | 
					
						
							|  |  |  | 	Fallthrough bool | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | // ServeDNS implements the plugin.Handler interface. | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | func (re Reverse) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { | 
					
						
							| 
									
										
										
										
											2017-02-20 21:00:00 +00:00
										 |  |  | 	var rr dns.RR | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	state := request.Request{W: w, Req: r} | 
					
						
							|  |  |  | 	m := new(dns.Msg) | 
					
						
							|  |  |  | 	m.SetReply(r) | 
					
						
							|  |  |  | 	m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 	switch state.QType() { | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 	case dns.TypePTR: | 
					
						
							|  |  |  | 		address := dnsutil.ExtractAddressFromReverse(state.Name()) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if address == "" { | 
					
						
							|  |  |  | 			// Not an reverse lookup, but can still be an pointer for an domain | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		ip := net.ParseIP(address) | 
					
						
							|  |  |  | 		// loop through the configured networks | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 		for _, n := range re.Networks { | 
					
						
							|  |  |  | 			if n.IPnet.Contains(ip) { | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 				rr = &dns.PTR{ | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 					Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: n.TTL}, | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 					Ptr: n.ipToHostname(ip), | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				break | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case dns.TypeA: | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 		for _, n := range re.Networks { | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 			if dns.IsSubDomain(n.Zone, state.Name()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// skip if requesting an v4 address and network is not v4 | 
					
						
							|  |  |  | 				if n.IPnet.IP.To4() == nil { | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				result := n.hostnameToIP(state.Name()) | 
					
						
							|  |  |  | 				if result != nil { | 
					
						
							|  |  |  | 					rr = &dns.A{ | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 						Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: n.TTL}, | 
					
						
							|  |  |  | 						A:   result, | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 					} | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	case dns.TypeAAAA: | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | 		for _, n := range re.Networks { | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 			if dns.IsSubDomain(n.Zone, state.Name()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// Do not use To16 which tries to make v4 in v6 | 
					
						
							|  |  |  | 				if n.IPnet.IP.To4() != nil { | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				result := n.hostnameToIP(state.Name()) | 
					
						
							|  |  |  | 				if result != nil { | 
					
						
							|  |  |  | 					rr = &dns.AAAA{ | 
					
						
							|  |  |  | 						Hdr:  dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: n.TTL}, | 
					
						
							|  |  |  | 						AAAA: result, | 
					
						
							|  |  |  | 					} | 
					
						
							|  |  |  | 					break | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 21:00:00 +00:00
										 |  |  | 	if rr != nil { | 
					
						
							|  |  |  | 		m.Answer = append(m.Answer, rr) | 
					
						
							|  |  |  | 		state.SizeAndDo(m) | 
					
						
							|  |  |  | 		w.WriteMsg(m) | 
					
						
							|  |  |  | 		return dns.RcodeSuccess, nil | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-20 21:00:00 +00:00
										 |  |  | 	if re.Fallthrough { | 
					
						
							| 
									
										
										
										
											2017-09-14 09:36:06 +01:00
										 |  |  | 		return plugin.NextOrFailure(re.Name(), re.Next, ctx, w, r) | 
					
						
							| 
									
										
										
										
											2017-02-20 21:00:00 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return dns.RcodeServerFailure, nil | 
					
						
							| 
									
										
										
										
											2017-02-09 20:39:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Name implements the Handler interface. | 
					
						
							| 
									
										
										
										
											2017-02-10 12:48:51 +00:00
										 |  |  | func (re Reverse) Name() string { return "reverse" } |