2018-07-20 19:45:17 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  loop  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"sync" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/coredns/coredns/plugin" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									clog  "github.com/coredns/coredns/plugin/pkg/log" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/coredns/coredns/request" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"github.com/miekg/dns" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  log  =  clog . NewWithPlugin ( "loop" )  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Loop is a plugin that implements loop detection by sending a "random" query.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  Loop  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Next  plugin . Handler 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									zone   string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									qname  string 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-16 21:48:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									addr   string 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-20 19:45:17 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									sync . RWMutex 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									i    int 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									off  bool 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// New returns a new initialized Loop.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  New ( zone  string )  * Loop  {  return  & Loop { zone :  zone ,  qname :  qname ( zone ) }  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// ServeDNS implements the plugin.Handler interface.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  ServeDNS ( ctx  context . Context ,  w  dns . ResponseWriter ,  r  * dns . Msg )  ( int ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  r . Question [ 0 ] . Qtype  !=  dns . TypeHINFO  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  plugin . NextOrFailure ( l . Name ( ) ,  l . Next ,  ctx ,  w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  l . disabled ( )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  plugin . NextOrFailure ( l . Name ( ) ,  l . Next ,  ctx ,  w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									state  :=  request . Request { W :  w ,  Req :  r } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									zone  :=  plugin . Zones ( [ ] string { l . zone } ) . Matches ( state . Name ( ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  zone  ==  ""  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  plugin . NextOrFailure ( l . Name ( ) ,  l . Next ,  ctx ,  w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  state . Name ( )  ==  l . qname  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										l . inc ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  l . seen ( )  >  2  { 
							 
						 
					
						
							
								
									
										
										
										
											2018-12-16 21:48:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										log . Fatalf ( ` Loop (%s -> %s) detected for zone %q, see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO %s" ` ,  state . RemoteAddr ( ) ,  l . address ( ) ,  l . zone ,  l . qname ) 
							 
						 
					
						
							
								
									
										
										
										
											2018-07-20 19:45:17 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  plugin . NextOrFailure ( l . Name ( ) ,  l . Next ,  ctx ,  w ,  r ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// Name implements the plugin.Handler interface.  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  Name ( )  string  {  return  "loop"  }  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  exchange ( addr  string )  ( * dns . Msg ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m  :=  new ( dns . Msg ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									m . SetQuestion ( l . qname ,  dns . TypeHINFO ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  dns . Exchange ( m ,  addr ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  seen ( )  int  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  l . i 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  inc ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . i ++ 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-10-31 18:20:43 +01:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( l  * Loop )  reset ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . i  =  0 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2018-07-20 19:45:17 +01:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  setDisabled ( )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . off  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  disabled ( )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  l . off 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2018-12-16 21:48:09 +00:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  setAddress ( addr  string )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . Lock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . Unlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . addr  =  addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( l  * Loop )  address ( )  string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									l . RLock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									defer  l . RUnlock ( ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  l . addr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}