From 8eedfcdb5ed7378915ff05eda1263d079ba33f7d Mon Sep 17 00:00:00 2001 From: Wagner Sartori Junior Date: Mon, 3 Feb 2020 16:56:22 +0100 Subject: [PATCH] Implement working DHCPv6 DDNS (Dynamic DNS) Follows PR #3909 and fixes #3908 --- src/etc/inc/plugins.inc.d/dhcpd.inc | 66 +++++++++++++++++++++-------- src/www/services_dhcpv6.php | 18 +++++++- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/etc/inc/plugins.inc.d/dhcpd.inc b/src/etc/inc/plugins.inc.d/dhcpd.inc index 628ae0088..0257ce8fa 100644 --- a/src/etc/inc/plugins.inc.d/dhcpd.inc +++ b/src/etc/inc/plugins.inc.d/dhcpd.inc @@ -1174,7 +1174,7 @@ EOD; } } -function dhcpd_zones($ddns_zones) +function dhcpd_zones($ddns_zones, $ipv6 = false) { $dhcpdconf = ''; @@ -1189,13 +1189,24 @@ function dhcpd_zones($ddns_zones) $primary = $zone['dns-servers'][0]; $secondary = empty($zone['dns-servers'][1]) ? "" : $zone['dns-servers'][1]; - // Make sure we aren't using any invalid or IPv6 DNS servers. - if (!is_ipaddrv4($primary)) { - if (is_ipaddrv4($secondary)) { - $primary = $secondary; - $secondary = ""; - } else { - continue; + // Make sure we aren't using any invalid DNS servers. + if ($ipv6) { + if (!is_ipaddrv6($primary)) { + if (is_ipaddrv6($secondary)) { + $primary = $secondary; + $secondary = ""; + } else { + continue; + } + } + } else { + if (!is_ipaddrv4($primary)) { + if (is_ipaddrv4($secondary)) { + $primary = $secondary; + $secondary = ""; + } else { + continue; + } } } @@ -1204,9 +1215,16 @@ function dhcpd_zones($ddns_zones) if (!empty($domain) && !in_array($domain, $added_zones)) { /* dhcpdconf2 is injected *after* the key */ $dhcpdconf2 = "zone {$domain}. {\n"; - $dhcpdconf2 .= " primary {$primary};\n"; - if (is_ipaddrv4($secondary)) { - $dhcpdconf2 .= " secondary {$secondary};\n"; + if ($ipv6) { + $dhcpdconf2 .= " primary6 {$primary};\n"; + if (is_ipaddrv6($secondary)) { + $dhcpdconf2 .= " secondary6 {$secondary};\n"; + } + } else { + $dhcpdconf2 .= " primary {$primary};\n"; + if (is_ipaddrv4($secondary)) { + $dhcpdconf2 .= " secondary {$secondary};\n"; + } } if (!empty($zone['ddnsdomainkeyname']) && !empty($zone['ddnsdomainkey'])) { if (!in_array($zone['ddnsdomainkeyname'], $added_keys)) { @@ -1407,7 +1425,7 @@ EOD; $dhcpdv6ifs = array(); $ddns_zones = array(); - $nsupdate = false; + $need_ddns_updates = false; foreach ($dhcpdv6cfg as $dhcpv6if => $dhcpv6ifconf) { if (!isset($dhcpv6ifconf['enable']) || !isset($iflist[$dhcpv6if])) { @@ -1435,6 +1453,7 @@ EOD; $newzone = array(); if (isset($dhcpv6ifconf['ddnsupdate'])) { + $need_ddns_updates = true; if (!empty($dhcpv6ifconf['ddnsdomain'])) { $dnscfgv6 .= " ddns-domainname \"{$dhcpv6ifconf['ddnsdomain']}\";\n"; $newzone['domain-name'] = $dhcpv6ifconf['ddnsdomain']; @@ -1442,7 +1461,20 @@ EOD; $newzone['domain-name'] = $config['system']['domain']; } - $nsupdate = true; + $subnetv6 = explode("/", $networkv6)[0]; + $addr = inet_pton($subnetv6); + $addr_unpack = unpack('H*hex', $addr); + $addr_hex = $addr_unpack['hex']; + $revsubnet = array_reverse(str_split($addr_hex)); + foreach ($revsubnet as $octet) { + if ($octet == "0") { + array_shift($revsubnet); + } else { + break; + } + } + + $newzone['ptr-domain'] = implode(".", $revsubnet) . ".ip6.arpa"; } if (isset($dhcpv6ifconf['dnsserver'][0])) { @@ -1550,8 +1582,7 @@ EOD; $newzone['dns-servers'] = array($dhcpv6ifconf['ddnsdomainprimary']); $newzone['ddnsdomainkeyname'] = $dhcpv6ifconf['ddnsdomainkeyname']; $newzone['ddnsdomainkey'] = $dhcpv6ifconf['ddnsdomainkey']; - /* XXX not implemented for IPv6 */ - $newzone['ddnsdomainalgorithm'] = 'hmac-md5'; + $newzone['ddnsdomainalgorithm'] = !empty($dhcpv6ifconf['ddnsdomainalgorithm']) ? $dhcpv6ifconf['ddnsdomainalgorithm'] : "hmac-md5"; $ddns_zones[] = $newzone; } } @@ -1572,9 +1603,10 @@ EOD; } } - if ($nsupdate) { + if ($need_ddns_updates) { $dhcpdv6conf .= "\nddns-update-style interim;\n"; - $dhcpdv6conf .= dhcpd_zones($ddns_zones); + $dhcpdv6conf .= "update-static-leases on;\n"; + $dhcpdv6conf .= dhcpd_zones($ddns_zones, $ipv6 = true); } else { $dhcpdv6conf .= "\nddns-update-style none;\n"; } diff --git a/src/www/services_dhcpv6.php b/src/www/services_dhcpv6.php index 89d433aa3..ee3c664fb 100644 --- a/src/www/services_dhcpv6.php +++ b/src/www/services_dhcpv6.php @@ -64,7 +64,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { $pconfig['prefixrange_length'] = $config['dhcpdv6'][$if]['prefixrange']['prefixlength']; } $config_copy_fieldsnames = array('defaultleasetime', 'maxleasetime', 'domainsearchlist', 'ddnsdomain', - 'ddnsdomainprimary', 'ddnsdomainkeyname', 'ddnsdomainkey', 'bootfile_url', 'netmask', + 'ddnsdomainprimary', 'ddnsdomainkeyname', 'ddnsdomainkey', 'ddnsdomainalgorithm', 'bootfile_url', 'netmask', 'numberoptions', 'dhcpv6leaseinlocaltime', 'staticmap'); foreach ($config_copy_fieldsnames as $fieldname) { if (isset($config['dhcpdv6'][$if][$fieldname])) { @@ -235,7 +235,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET') { // simple 1-on-1 copy $config_copy_fieldsnames = array('defaultleasetime', 'maxleasetime', 'netmask', 'domainsearchlist', - 'ddnsdomain', 'ddnsdomainprimary', 'ddnsdomainkeyname', 'ddnsdomainkey', 'bootfile_url', + 'ddnsdomain', 'ddnsdomainprimary', 'ddnsdomainkeyname', 'ddnsdomainkey', 'ddnsdomainalgorithm', 'bootfile_url', 'dhcpv6leaseinlocaltime'); foreach ($config_copy_fieldsnames as $fieldname) { if (!empty($pconfig[$fieldname])) { @@ -612,6 +612,20 @@ if (isset($config['interfaces'][$if]['dhcpd6track6allowoverride'])) { +
+