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 
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}