| 
									
										
										
										
											2019-11-15 14:14:29 +00:00
										 |  |  | // Package fall handles the fallthrough logic used in plugins that support it. Be careful when including this
 | 
					
						
							|  |  |  | // functionality in your plugin. Why? In the DNS only 1 source is authoritative for a set of names. Fallthrough
 | 
					
						
							|  |  |  | // breaks this convention by allowing a plugin to query multiple sources, depending on the replies it got sofar.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This may cause issues in downstream caches, where different answers for the same query can potentially confuse clients.
 | 
					
						
							|  |  |  | // On the other hand this is a powerful feature that can aid in migration or other edge cases.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The take away: be mindful of this and don't blindly assume it's a good feature to have in your plugin.
 | 
					
						
							|  |  |  | //
 | 
					
						
							| 
									
										
										
										
											2020-02-18 14:08:10 +07:00
										 |  |  | // See https://github.com/coredns/coredns/issues/2723 for some discussion on this, which includes this quote:
 | 
					
						
							| 
									
										
										
										
											2019-11-15 14:14:29 +00:00
										 |  |  | //
 | 
					
						
							|  |  |  | // TL;DR: `fallthrough` is indeed risky and hackish, but still a good feature of CoreDNS as it allows to quickly answer boring edge cases.
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | package fall
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							| 
									
										
										
										
											2025-07-29 03:04:53 +08:00
										 |  |  | 	"slices"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 	"github.com/coredns/coredns/plugin"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // F can be nil to allow for no fallthrough, empty allow all zones to fallthrough or
 | 
					
						
							|  |  |  | // contain a zone list that is checked.
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | type F struct {
 | 
					
						
							|  |  |  | 	Zones []string
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Through will check if we should fallthrough for qname. Note that we've named the
 | 
					
						
							|  |  |  | // variable in each plugin "Fall", so this then reads Fall.Through().
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | func (f F) Through(qname string) bool {
 | 
					
						
							|  |  |  | 	return plugin.Zones(f.Zones).Matches(qname) != ""
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | // setZones will set zones in f.
 | 
					
						
							|  |  |  | func (f *F) setZones(zones []string) {
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 	z := []string{}
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 	for i := range zones {
 | 
					
						
							| 
									
										
										
										
											2021-05-27 07:26:14 -04:00
										 |  |  | 		z = append(z, plugin.Host(zones[i]).NormalizeExact()...)
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | 	f.Zones = z
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | // SetZonesFromArgs sets zones in f to the passed value or to "." if the slice is empty.
 | 
					
						
							|  |  |  | func (f *F) SetZonesFromArgs(zones []string) {
 | 
					
						
							|  |  |  | 	if len(zones) == 0 {
 | 
					
						
							| 
									
										
										
										
											2018-01-09 22:29:19 +00:00
										 |  |  | 		f.setZones(Root.Zones)
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | 		return
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | 	}
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | 	f.setZones(zones)
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | // Equal returns true if f and g are equal.
 | 
					
						
							| 
									
										
										
										
											2021-05-17 22:19:54 +02:00
										 |  |  | func (f *F) Equal(g F) bool {
 | 
					
						
							| 
									
										
										
										
											2025-07-29 03:04:53 +08:00
										 |  |  | 	return slices.Equal(f.Zones, g.Zones)
 | 
					
						
							| 
									
										
										
										
											2018-01-07 16:32:59 +00:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Zero returns a zero valued F.
 | 
					
						
							|  |  |  | var Zero = func() F {
 | 
					
						
							|  |  |  | 	return F{[]string{}}
 | 
					
						
							| 
									
										
										
										
											2018-01-09 22:29:19 +00:00
										 |  |  | }()
 | 
					
						
							| 
									
										
										
										
											2018-01-07 14:51:32 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | // Root returns F set to only ".".
 | 
					
						
							|  |  |  | var Root = func() F {
 | 
					
						
							|  |  |  | 	return F{[]string{"."}}
 | 
					
						
							| 
									
										
										
										
											2018-01-09 22:29:19 +00:00
										 |  |  | }()
 |