mirror of
				https://github.com/coredns/coredns.git
				synced 2025-10-29 01:04:15 -04:00 
			
		
		
		
	
		
			
	
	
		
			75 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			75 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|   | // Package cidr contains functions that deal with classless reverse zones in the DNS. | ||
|  | package cidr | ||
|  | 
 | ||
|  | import ( | ||
|  | 	"math" | ||
|  | 	"net" | ||
|  | 
 | ||
|  | 	"github.com/apparentlymart/go-cidr/cidr" | ||
|  | 	"github.com/miekg/dns" | ||
|  | ) | ||
|  | 
 | ||
|  | // Class return slice of "classful" (/8, /16, /24 or /32 only) CIDR's from the CIDR in net. | ||
|  | func Class(n *net.IPNet) []string { | ||
|  | 	ones, _ := n.Mask.Size() | ||
|  | 	if ones%8 == 0 { | ||
|  | 		return []string{n.String()} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	mask := int(math.Ceil(float64(ones)/8)) * 8 | ||
|  | 	networks := nets(n, mask) | ||
|  | 	cidrs := make([]string, len(networks)) | ||
|  | 	for i := range networks { | ||
|  | 		cidrs[i] = networks[i].String() | ||
|  | 	} | ||
|  | 	return cidrs | ||
|  | } | ||
|  | 
 | ||
|  | // nets return a slice of prefixes with the desired mask subnetted from original network. | ||
|  | func nets(network *net.IPNet, newPrefixLen int) []*net.IPNet { | ||
|  | 	prefixLen, _ := network.Mask.Size() | ||
|  | 	maxSubnets := int(math.Exp2(float64(newPrefixLen)) / math.Exp2(float64(prefixLen))) | ||
|  | 	nets := []*net.IPNet{{network.IP, net.CIDRMask(newPrefixLen, 8*len(network.IP))}} | ||
|  | 
 | ||
|  | 	for i := 1; i < maxSubnets; i++ { | ||
|  | 		next, exceeds := cidr.NextSubnet(nets[len(nets)-1], newPrefixLen) | ||
|  | 		nets = append(nets, next) | ||
|  | 		if exceeds { | ||
|  | 			break | ||
|  | 		} | ||
|  | 	} | ||
|  | 
 | ||
|  | 	return nets | ||
|  | } | ||
|  | 
 | ||
|  | // Reverse return the reverse zones that are authoritative for each net in ns. | ||
|  | func Reverse(nets []string) []string { | ||
|  | 	rev := make([]string, len(nets)) | ||
|  | 	for i := range nets { | ||
|  | 		ip, n, _ := net.ParseCIDR(nets[i]) | ||
|  | 		r, err1 := dns.ReverseAddr(ip.String()) | ||
|  | 		if err1 != nil { | ||
|  | 			continue | ||
|  | 		} | ||
|  | 		ones, bits := n.Mask.Size() | ||
|  | 		// get the size, in bits, of each portion of hostname defined in the reverse address. (8 for IPv4, 4 for IPv6) | ||
|  | 		sizeDigit := 8 | ||
|  | 		if len(n.IP) == net.IPv6len { | ||
|  | 			sizeDigit = 4 | ||
|  | 		} | ||
|  | 		// Get the first lower octet boundary to see what encompassing zone we should be authoritative for. | ||
|  | 		mod := (bits - ones) % sizeDigit | ||
|  | 		nearest := (bits - ones) + mod | ||
|  | 		offset := 0 | ||
|  | 		var end bool | ||
|  | 		for i := 0; i < nearest/sizeDigit; i++ { | ||
|  | 			offset, end = dns.NextLabel(r, offset) | ||
|  | 			if end { | ||
|  | 				break | ||
|  | 			} | ||
|  | 		} | ||
|  | 		rev[i] = r[offset:] | ||
|  | 	} | ||
|  | 	return rev | ||
|  | } |