1
0
mirror of https://github.com/StackExchange/dnscontrol.git synced 2024-05-11 05:55:12 +00:00

Fix REV and PTR (#979)

* Fix REV and PTR
This commit is contained in:
Tom Limoncelli
2020-12-03 08:33:37 -05:00
committed by GitHub
parent 2e7311078c
commit 6443a31ca8
9 changed files with 318 additions and 133 deletions

View File

@ -884,7 +884,9 @@
<td class="success"> <td class="success">
<i class="fa fa-check text-success" aria-hidden="true"></i> <i class="fa fa-check text-success" aria-hidden="true"></i>
</td> </td>
<td><i class="fa fa-minus dim"></i></td> <td class="success">
<i class="fa fa-check text-success" aria-hidden="true"></i>
</td>
<td><i class="fa fa-minus dim"></i></td> <td><i class="fa fa-minus dim"></i></td>
<td><i class="fa fa-minus dim"></i></td> <td><i class="fa fa-minus dim"></i></td>
<td><i class="fa fa-minus dim"></i></td> <td><i class="fa fa-minus dim"></i></td>

View File

@ -682,12 +682,17 @@ function recordBuilder(type, opts) {
opts.transform(record, parsedArgs, modifiers); opts.transform(record, parsedArgs, modifiers);
// Handle D_EXTEND() with subdomains. // Handle D_EXTEND() with subdomains.
if (d.subdomain && record.type != 'CF_REDIRECT' && if (d.subdomain &&
record.type != 'CF_TEMP_REDIRECT') { record.type != 'CF_REDIRECT' &&
record.type != 'CF_TEMP_REDIRECT') {
fqdn = [d.subdomain, d.name].join(".")
record.subdomain = d.subdomain; record.subdomain = d.subdomain;
if (record.name == '@') { if (record.name == '@') {
record.subdomain = d.subdomain;
record.name = d.subdomain; record.name = d.subdomain;
} else { } else if (fqdn != record.name && record.type != 'PTR') {
record.subdomain = d.subdomain;
record.name += '.' + d.subdomain; record.name += '.' + d.subdomain;
} }
} }

View File

@ -0,0 +1,29 @@
var REGISTRAR = NewRegistrar('none', 'NONE'); // No registrar.
var BIND = NewDnsProvider('bind', 'BIND');
D(REV('1.2.3.0/24'), REGISTRAR, DnsProvider(BIND),
PTR("1", 'foo.example.com.'),
PTR("1.2.3.2", 'bar.example.com.'),
PTR(REV("1.2.3.3"), 'baz.example.com.', {skip_fqdn_check:"true"})
);
D_EXTEND(REV("1.2.3.4"), PTR("4", "silly.example.com."))
D_EXTEND(REV("1.2.3.5"), PTR("1.2.3.5", "willy.example.com."))
D_EXTEND(REV("1.2.3.6"), PTR(REV("1.2.3.6"), "billy.example.com."))
D_EXTEND(REV("1.2.3.0/24"), PTR("7", "my.example.com."))
D_EXTEND(REV("1.2.3.0/24"), PTR("1.2.3.8", "fair.example.com."))
D_EXTEND(REV("1.2.3.0/24"), PTR(REV("1.2.3.9/32"), "lady.example.com.", {skip_fqdn_check:"true"}))
// Expected zone: 3.2.1.in-addr.arpa.zone
// $TTL 300
//; generated with dnscontrol 2020-11-30T12:56:28-05:00
//@ IN SOA DEFAULT_NOT_SET. DEFAULT_NOT_SET. 2020113000 3600 600 604800 1440
//1 IN PTR foo.example.com.
//2 IN PTR bar.example.com.
//3 IN PTR baz.example.com.
//4 IN PTR silly.example.com.
//5 IN PTR willy.example.com.
//6 IN PTR billy.example.com.
//7 IN PTR my.example.com.
//8 IN PTR fair.example.com.
//9 IN PTR lady.example.com.

View File

@ -0,0 +1,79 @@
{
"dns_providers": [
{
"name": "bind",
"type": "BIND"
}
],
"domains": [
{
"dnsProviders": {
"bind": -1
},
"name": "3.2.1.in-addr.arpa",
"records": [
{
"name": "1",
"target": "foo.example.com.",
"type": "PTR"
},
{
"name": "1.2.3.2",
"target": "bar.example.com.",
"type": "PTR"
},
{
"meta": {
"skip_fqdn_check": "true"
},
"name": "3.3.2.1.in-addr.arpa",
"target": "baz.example.com.",
"type": "PTR"
},
{
"name": "4",
"subdomain": "4",
"target": "silly.example.com.",
"type": "PTR"
},
{
"name": "1.2.3.5",
"subdomain": "5",
"target": "willy.example.com.",
"type": "PTR"
},
{
"name": "6.3.2.1.in-addr.arpa",
"subdomain": "6",
"target": "billy.example.com.",
"type": "PTR"
},
{
"name": "7",
"target": "my.example.com.",
"type": "PTR"
},
{
"name": "1.2.3.8",
"target": "fair.example.com.",
"type": "PTR"
},
{
"meta": {
"skip_fqdn_check": "true"
},
"name": "9.3.2.1.in-addr.arpa",
"target": "lady.example.com.",
"type": "PTR"
}
],
"registrar": "none"
}
],
"registrars": [
{
"name": "none",
"type": "NONE"
}
]
}

View File

@ -0,0 +1,15 @@
var REGISTRAR = NewRegistrar('none', 'NONE'); // No registrar.
var BIND = NewDnsProvider('bind', 'BIND');
// Delegating reverse zones
D(REV('1.3.0.0/16'), REGISTRAR, DnsProvider(BIND),
NS(REV('1.3.1.0/24'), "ns1.example.com.")
);
D_EXTEND(REV("1.3.2.0/24"), NS(REV("1.3.2.0/24"), "ns2.example.org."))
// Expeccted zone: 3.1.in-addr.arpa.zone
// $TTL 300
// ; generated with dnscontrol 2020-11-30T12:58:47-05:00
// @ IN SOA DEFAULT_NOT_SET. DEFAULT_NOT_SET. 2020113000 3600 600 604800 1440
// 1 IN NS ns1.example.com.
// 2 IN NS ns2.example.org.

View File

@ -0,0 +1,36 @@
{
"dns_providers": [
{
"name": "bind",
"type": "BIND"
}
],
"domains": [
{
"dnsProviders": {
"bind": -1
},
"name": "3.1.in-addr.arpa",
"records": [
{
"name": "1.3.1.in-addr.arpa",
"target": "ns1.example.com.",
"type": "NS"
},
{
"name": "2.3.1.in-addr.arpa",
"subdomain": "2",
"target": "ns2.example.org.",
"type": "NS"
}
],
"registrar": "none"
}
],
"registrars": [
{
"name": "none",
"type": "NONE"
}
]
}

View File

@ -212,134 +212,135 @@ var _escData = map[string]*_escFile{
"/helpers.js": { "/helpers.js": {
name: "helpers.js", name: "helpers.js",
local: "pkg/js/helpers.js", local: "pkg/js/helpers.js",
size: 28419, size: 28640,
modtime: 0, modtime: 0,
compressed: ` compressed: `
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
bW+i4G8AAA==
`, `,
}, },
} }

View File

@ -98,9 +98,9 @@ func checkLabel(label string, rType string, target, domain string, meta map[stri
if label[len(label)-1] == '.' { if label[len(label)-1] == '.' {
return fmt.Errorf("label %s.%s ends with a (.)", label, domain) return fmt.Errorf("label %s.%s ends with a (.)", label, domain)
} }
if strings.HasSuffix(label, domain) { if label == domain || strings.HasSuffix(label, "."+domain) {
if m := meta["skip_fqdn_check"]; m != "true" { if m := meta["skip_fqdn_check"]; m != "true" {
return fmt.Errorf(`label %s ends with domain name %s. Record names should not be fully qualified. Add {skip_fqdn_check:"true"} to this record if you really want to make %s.%s`, label, domain, label, domain) return fmt.Errorf(`label %q ends with domain name %q. Record names should not be fully qualified. Add {skip_fqdn_check:"true"} to this record if you really want to make %s.%s`, label, domain, label, domain)
} }
} }
@ -281,6 +281,13 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
if rec.TTL == 0 { if rec.TTL == 0 {
rec.TTL = models.DefaultTTL rec.TTL = models.DefaultTTL
} }
// in-addr.arpa magic
if strings.HasSuffix(domain.Name, ".in-addr.arpa") || strings.HasSuffix(domain.Name, ".ip6.arpa") {
label := rec.GetLabel()
if label == domain.Name || strings.HasSuffix(label, "."+domain.Name) {
rec.SetLabel(label[0:(len(label)-len("."+domain.Name))], domain.Name)
}
}
// Validate the unmodified inputs: // Validate the unmodified inputs:
if err := validateRecordTypes(rec, domain.Name, pTypes); err != nil { if err := validateRecordTypes(rec, domain.Name, pTypes); err != nil {
errs = append(errs, err) errs = append(errs, err)
@ -299,7 +306,7 @@ func ValidateAndNormalizeConfig(config *models.DNSConfig) (errs []error) {
// We normalize them to a FQDN so there is less variation to handle. If a // We normalize them to a FQDN so there is less variation to handle. If a
// provider API requires a shortname, the provider must do the shortening. // provider API requires a shortname, the provider must do the shortening.
origin := domain.Name + "." origin := domain.Name + "."
if len(rec.SubDomain) > 0 { if rec.SubDomain != "" {
origin = rec.SubDomain + "." + origin origin = rec.SubDomain + "." + origin
} }
rec.SetTarget(dnsutil.AddOrigin(rec.GetTargetField(), origin)) rec.SetTarget(dnsutil.AddOrigin(rec.GetTargetField(), origin))

View File

@ -8,6 +8,17 @@ import (
// ReverseDomainName turns a CIDR block into a reversed (in-addr) name. // ReverseDomainName turns a CIDR block into a reversed (in-addr) name.
func ReverseDomainName(cidr string) (string, error) { func ReverseDomainName(cidr string) (string, error) {
// If it is an IP address, add the /32 or /128
ip := net.ParseIP(cidr)
if ip != nil {
if ip.To4() != nil {
cidr = cidr + "/32"
} else {
cidr = cidr + "/128"
}
}
a, c, err := net.ParseCIDR(cidr) a, c, err := net.ParseCIDR(cidr)
if err != nil { if err != nil {
return "", err return "", err