2017-06-05 14:26:59 -04:00
|
|
|
package transform
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
2024-04-03 16:01:55 -04:00
|
|
|
"net/netip"
|
2017-06-05 14:26:59 -04:00
|
|
|
"strings"
|
2024-04-03 16:01:55 -04:00
|
|
|
|
|
|
|
"github.com/StackExchange/dnscontrol/v4/pkg/rfc4183"
|
2017-06-05 14:26:59 -04:00
|
|
|
)
|
|
|
|
|
2018-01-09 12:53:16 -05:00
|
|
|
// ReverseDomainName turns a CIDR block into a reversed (in-addr) name.
|
2024-04-03 16:01:55 -04:00
|
|
|
// For cases not covered by RFC2317, implement RFC4183
|
|
|
|
// The host bits must all be zeros.
|
2017-06-05 14:26:59 -04:00
|
|
|
func ReverseDomainName(cidr string) (string, error) {
|
2020-12-03 08:33:37 -05:00
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
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() {
|
2020-12-03 08:33:37 -05:00
|
|
|
cidr = cidr + "/32"
|
|
|
|
} else {
|
|
|
|
cidr = cidr + "/128"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
// Parse the CIDR.
|
|
|
|
p, err := netip.ParsePrefix(cidr)
|
2017-06-05 14:26:59 -04:00
|
|
|
if err != nil {
|
2024-04-03 16:01:55 -04:00
|
|
|
return "", fmt.Errorf("not a CIDR block: %w", err)
|
2017-06-05 14:26:59 -04:00
|
|
|
}
|
2024-04-03 16:01:55 -04:00
|
|
|
bits := p.Bits()
|
2017-07-10 19:24:55 -04:00
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
if p.Masked() != p {
|
|
|
|
return "", fmt.Errorf("CIDR %v has 1 bits beyond the mask", cidr)
|
2017-07-10 19:24:55 -04:00
|
|
|
}
|
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
// 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)
|
2017-06-05 14:26:59 -04:00
|
|
|
}
|
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
// Record that the change to --revmode default will affect this configuration
|
|
|
|
rfc4183.NeedsWarning()
|
2017-06-05 14:26:59 -04:00
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
// Handle IPv4 "Classless in-addr.arpa delegation" RFC2317:
|
|
|
|
// if bits >= 25 && bits < 32 {
|
|
|
|
// first address / netmask . Class-b-arpa.
|
2017-06-05 14:26:59 -04:00
|
|
|
|
2024-04-03 16:01:55 -04:00
|
|
|
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
|
2017-06-05 14:26:59 -04:00
|
|
|
}
|