mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2025-01-11 01:47:53 +08:00
1d96981e11
Co-authored-by: Thomas Misilo <tmisilo@ksu.edu> Co-authored-by: Jeffrey Cafferata <jeffrey@jcid.nl>
61 lines
1.5 KiB
Go
61 lines
1.5 KiB
Go
package transform
|
|
|
|
import (
|
|
"fmt"
|
|
"net/netip"
|
|
"strings"
|
|
|
|
"github.com/StackExchange/dnscontrol/v4/pkg/rfc4183"
|
|
)
|
|
|
|
// ReverseDomainName turns a CIDR block into a reversed (in-addr) name.
|
|
// For cases not covered by RFC2317, implement RFC4183
|
|
// The host bits must all be zeros.
|
|
func ReverseDomainName(cidr string) (string, error) {
|
|
|
|
if rfc4183.IsRFC4183Mode() {
|
|
return rfc4183.ReverseDomainName(cidr)
|
|
}
|
|
|
|
// Mask missing? Add it.
|
|
if !strings.Contains(cidr, "/") {
|
|
a, err := netip.ParseAddr(cidr)
|
|
if err != nil {
|
|
return "", fmt.Errorf("not an IP address: %w", err)
|
|
}
|
|
if a.Is4() {
|
|
cidr = cidr + "/32"
|
|
} else {
|
|
cidr = cidr + "/128"
|
|
}
|
|
}
|
|
|
|
// Parse the CIDR.
|
|
p, err := netip.ParsePrefix(cidr)
|
|
if err != nil {
|
|
return "", fmt.Errorf("not a CIDR block: %w", err)
|
|
}
|
|
bits := p.Bits()
|
|
|
|
if p.Masked() != p {
|
|
return "", fmt.Errorf("CIDR %v has 1 bits beyond the mask", cidr)
|
|
}
|
|
|
|
// Cases where RFC4183 is the same as RFC2317:
|
|
// IPV6, /0 - /24, /32
|
|
if strings.Contains(cidr, ":") || bits <= 24 || bits == 32 {
|
|
// There is no p.Is6() so we test for ":" as a workaround.
|
|
return rfc4183.ReverseDomainName(cidr)
|
|
}
|
|
|
|
// Record that the change to --revmode default will affect this configuration
|
|
rfc4183.NeedsWarning()
|
|
|
|
// Handle IPv4 "Classless in-addr.arpa delegation" RFC2317:
|
|
// if bits >= 25 && bits < 32 {
|
|
// first address / netmask . Class-b-arpa.
|
|
|
|
ip := p.Addr().AsSlice()
|
|
return fmt.Sprintf("%d/%d.%d.%d.%d.in-addr.arpa",
|
|
ip[3], bits, ip[2], ip[1], ip[0]), nil
|
|
}
|