mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
PTR should handle "Classless in-addr.arpa delegation" RFC2317 (#149)
* Handle IPv4 "Classless in-addr.arpa delegation" RFC2317 (partial). * Validate PTR name when in RFC2317 "Classless in-addr.arpa delegation" domains. * Update docs * Set CanUsePTR for Route53 and Google CloudDNS. * BIND: Replace "/" with "_" in filenames.
This commit is contained in:
@ -1,7 +1,10 @@
|
||||
package transform
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -44,10 +47,56 @@ func ipv4magic(name, domain string) (string, error) {
|
||||
if err != nil {
|
||||
return name, err
|
||||
}
|
||||
if !strings.HasSuffix(rev, "."+domain) {
|
||||
err = errors.Errorf("ERROR: PTR record %v in wrong IPv4 domain (%v)", name, domain)
|
||||
result := strings.TrimSuffix(rev, "."+domain)
|
||||
|
||||
// Are we in the right domain?
|
||||
if strings.HasSuffix(rev, "."+domain) {
|
||||
return result, nil
|
||||
}
|
||||
return strings.TrimSuffix(rev, "."+domain), err
|
||||
if ipMatchesClasslessDomain(ip, domain) {
|
||||
return strings.SplitN(rev, ".", 2)[0], nil
|
||||
}
|
||||
|
||||
return "", errors.Errorf("PTR record %v in wrong IPv4 domain (%v)", name, domain)
|
||||
}
|
||||
|
||||
var isRfc2317Format1 = regexp.MustCompile(`(\d{1,3})/(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.in-addr\.arpa$`)
|
||||
|
||||
// ipMatchesClasslessDomain returns true if ip is appropriate for domain.
|
||||
// domain is a reverse DNS lookup zone (in-addr.arpa) as described in RFC2317.
|
||||
func ipMatchesClasslessDomain(ip net.IP, domain string) bool {
|
||||
|
||||
// The unofficial but preferred format in RFC2317:
|
||||
m := isRfc2317Format1.FindStringSubmatch(domain)
|
||||
if m != nil {
|
||||
// IP: Domain:
|
||||
// 172.20.18.27 128/27.18.20.172.in-addr.arpa
|
||||
// A B C D F M X Y Z
|
||||
// The following should be true:
|
||||
// A==Z, B==Y, C==X.
|
||||
// If you mask ip by M, the last octet should be F.
|
||||
ii := ip.To4()
|
||||
a, b, c, _ := ii[0], ii[1], ii[2], ii[3]
|
||||
f, m, x, y, z := atob(m[1]), atob(m[2]), atob(m[3]), atob(m[4]), atob(m[5])
|
||||
masked := ip.Mask(net.CIDRMask(int(m), 32))
|
||||
if a == z && b == y && c == x && masked.Equal(net.IPv4(a, b, c, f)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// To extend this to include other formats, add them here.
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// atob converts a to a byte value or panics.
|
||||
func atob(s string) byte {
|
||||
if i, err := strconv.Atoi(s); err == nil {
|
||||
if i < 256 {
|
||||
return byte(i)
|
||||
}
|
||||
}
|
||||
panic(fmt.Sprintf("(%v) matched \\d{1,3} but is not a byte", s))
|
||||
}
|
||||
|
||||
func ipv6magic(name, domain string) (string, error) {
|
||||
@ -63,7 +112,7 @@ func ipv6magic(name, domain string) (string, error) {
|
||||
return name, err
|
||||
}
|
||||
if !strings.HasSuffix(rev, "."+domain) {
|
||||
err = errors.Errorf("ERROR: PTR record %v in wrong IPv6 domain (%v)", name, domain)
|
||||
err = errors.Errorf("PTR record %v in wrong IPv6 domain (%v)", name, domain)
|
||||
}
|
||||
return strings.TrimSuffix(rev, "."+domain), err
|
||||
}
|
||||
|
Reference in New Issue
Block a user