Regression #16045
closedDynamic DNS IPv6 tries to use IPv4 address
Added by Bart Schapendonk 2 months ago. Updated about 1 month ago.
100%
Description
Feb 13 08:49:54 php-fpm 34382 /services_dyndns_edit.php: Dynamic DNS: updatedns() starting
Feb 13 08:49:54 php-fpm 34382 /services_dyndns_edit.php: Dynamic DNS cloudflare-v6 (wg.example.com): _update() starting.
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: HTTP/2 400
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: date: Thu, 13 Feb 2025 07:49:55 GMT
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: content-type: application/json
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: cf-ray: <REDACTED>
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: cf-cache-status: DYNAMIC
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: set-cookie: __cflb=<REDACTED>; SameSite=Lax; path=/; expires=Thu, 13-Feb-25 10:19:56 GMT; HttpOnly
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: vary: Accept-Encoding
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: cf-auditlog-id: 0194fe49-29cb-718a-9cb1-da60775f27ca
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: set-cookie: __cf_bm=<REDACTED>; path=/; expires=Thu, 13-Feb-25 08:19:55 GMT; domain=.api.cloudflare.com; HttpOnly; Secure; SameSite=None
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: set-cookie: __cfruid=<REDACTED>; path=/; domain=.api.cloudflare.com; HttpOnly; Secure; SameSite=None
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: set-cookie: _cfuvid=<REDACTED>; path=/; domain=.api.cloudflare.com; HttpOnly; Secure; SameSite=None
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header: server: cloudflare
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header:
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Header:
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Response Data: {"result":null,"success":false,"errors":[{"code":9006,"message":"Content for AAAA record must be a valid IPv6 address."}],"messages":[]}
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Dynamic DNS cloudflare-v6 (wg.example.com): _checkStatus() starting.
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: phpDynDNS (wg): PAYLOAD: {"result":null,"success":false,"errors":[{"code":9006,"message":"Content for AAAA record must be a valid IPv6 address."}],"messages":[]}
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: phpDynDNS (wg): UNKNOWN ERROR - Content for AAAA record must be a valid IPv6 address.
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Dynamic DNS cloudflare-v6 (wg.example.com): _checkStatus() ending.
Feb 13 08:49:55 php-fpm 34382 /services_dyndns_edit.php: Dynamic DNS cloudflare-v6 (wg.example.com): _update() ending.
Updated by Bart Schapendonk 2 months ago
Sorry, my cat slapped the submit button whith his tail before I could finish.
This is on: "25.03-BETA (amd64) built on Tue Feb 4 1:23:00 CET 2025", it worked on 24.11.
I added the following line log_error(sprintf("dnsIP: %s", $this->_dnsIP));
above $response = curl_exec($ch);
(https://github.com/pfsense/pfsense/blob/ba43ae3191b64ff05a60f1faca79a6ad0d127abc/src/etc/inc/dyndns.class#L1792) of the IP that is being used to update the AAAA record.
This resulted in a IPv4 address instead of a IPv6 address.
Feb 13 10:21:13 php-fpm 97602 /services_dyndns_edit.php: Dynamic DNS cloudflare-v6 (wg.example.com): _update() starting.
Feb 13 10:21:14 php-fpm 97602 /services_dyndns_edit.php: dnsIP: 149.143.x.x
Updated by Bart Schapendonk 2 months ago
This patch fixes some things and at first glance it looks to work?
But most likely its broken in more places. Looks like the issues is that _addressFamily
is null
and this falling back to AF_INET
. I found two places where it should be set to AF_INET6
.
diff --git a/src/etc/inc/dyndns.class b/src/etc/inc/dyndns.class
index 5c1f6ae0f4..31f07b38ea 100644
--- a/src/etc/inc/dyndns.class
+++ b/src/etc/inc/dyndns.class
@@ -357,7 +357,7 @@
case 'route53-v6':
case 'spdyn-v6':
case 'yandex-v6':
- $this->_addressFamily = $this->_curlIpresolveV4 ? AF_INET : null;
+ $this->_addressFamily = $this->_curlIpresolveV4 ? AF_INET : AF_INET6;
break;
default:
$this->_addressFamily = null;
diff --git a/src/usr/local/www/services_dyndns.php b/src/usr/local/www/services_dyndns.php
index 94a96f1833..26fbaadf0c 100644
--- a/src/usr/local/www/services_dyndns.php
+++ b/src/usr/local/www/services_dyndns.php
@@ -128,7 +128,7 @@ foreach (config_get_path("dyndnses/dyndns", []) as $dyndns):
$icon_title = "Failed";
}
} else if (file_exists($filename_v6)) {
- $ipv6addr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'));
+ $ipv6addr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'), AF_INET6);
$cached_ipv6_s = explode("|", file_get_contents($filename_v6));
$cached_ipv6 = $cached_ipv6_s[0];
---
I can't reply (Plus target version cannot be blank), but edit seems to work.
The new patch still pushes a IPv4 value, I believe this because $this->_addressFamily
still has an invalide value and is used later on to switch between V4 and V6 behaviour.
Updated by Marcos M 2 months ago
- Status changed from New to In Progress
Please try the following patch: ShowHide
diff --git a/src/etc/inc/dyndns.class b/src/etc/inc/dyndns.class
index 5c1f6ae0f4..23174464e3 100644
--- a/src/etc/inc/dyndns.class
+++ b/src/etc/inc/dyndns.class
@@ -196,7 +196,16 @@
var $_dnsDummyUpdateDone;
var $_forceUpdateNeeded;
var $_checkIPMode;
- var $_addressFamily;
+
+ /**
+ * The $_addressFamilyRR variable is used along with $_dnsIP to
+ * determine the data for the resource record. It is independent
+ * of $_addressFamilyRequest which determines the IP address
+ * family used to make the request itself.
+ */
+ var $_addressFamilyRR;
+ var $_addressFamilyRequest;
+
var $_existingRecords;
var $_curlProxy;
@@ -357,10 +366,10 @@
case 'route53-v6':
case 'spdyn-v6':
case 'yandex-v6':
- $this->_addressFamily = $this->_curlIpresolveV4 ? AF_INET : null;
+ $this->_addressFamilyRR = AF_INET6;
break;
default:
- $this->_addressFamily = null;
+ $this->_addressFamilyRR = AF_INET;
}
$this->_dnsService = strtolower($dnsService);
$this->_dnsUser = $dnsUser;
@@ -378,10 +387,25 @@
$this->_dnsUpdateURL = $dnsUpdateURL;
$this->_dnsResultMatch = $dnsResultMatch;
$this->_dnsRequestIf = $dnsRequestIf;
- $this->_dnsRequestIfIP = get_request_source_address($this->_dnsRequestIf, $this->_addressFamily);
- $this->_addressFamily = is_ipaddrv6($this->_dnsRequestIfIP) ? AF_INET6 : AF_INET;
+
+ /**
+ * The request's source IP address is chosen as follows:
+ * If IPv4 is forced by $_curlIpresolveV4 then the source IP
+ * is set to the primary IPv4 address of the "interface to
+ * monitor". When the "interface to monitor" only has either
+ * IPv4 or IPv6, the the respective "primary" address for the
+ * interface is chosen. If both IPv4 and IPv6 addresses exist
+ * on the "interface to monitor", the chosen address depends
+ * on the system preference ("prefer_ipv4").
+ *
+ * To instead choose the source IP address based on the DNS RR
+ * type, replace 'null' with '$this->_addressFamilyRR'.
+ */
+ $this->_dnsRequestIfIP = get_request_source_address($this->_dnsRequestIf, ($this->_curlIpresolveV4 ? AF_INET : null));
+
+ $this->_addressFamilyRequest = is_ipaddrv6($this->_dnsRequestIfIP) ? AF_INET6 : AF_INET;
$this->_checkIPMode = $checkIPMode;
- $this->_dnsIP = dyndnsCheckIP($this->_dnsRequestIf, $this->_checkIPMode, $this->_addressFamily);
+ $this->_dnsIP = dyndnsCheckIP($this->_dnsRequestIf, $this->_checkIPMode, $this->_addressFamilyRR);
if (($dnsMaxCacheAge !== null) && ($dnsMaxCacheAge !== "")) {
$this->_dnsMaxCacheAgeDays = (int)$dnsMaxCacheAge;
@@ -533,7 +557,7 @@
$ch = curl_init();
- curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamily == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
+ curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamilyRequest == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
if ($this->_dnsService != 'ods') {
curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
@@ -875,7 +899,7 @@
https://{login}:{password}@https://api.mythic-beasts.com/dns/v2/zones/example.com/records/test1/A -d data=1.2.3.4
*/
$needsIP = FALSE;
- if ($this->_addressFamily == AF_INET6) {
+ if ($this->_addressFamilyRR == AF_INET6) {
$record = "AAAA";
} else {
$record = "A";
@@ -891,7 +915,7 @@
// API documentation: https://www.name.com/api-docs/ & https://www.name.com/api-docs/dns
$namedotcom_api = "https://api.name.com/v4/domains/{$this->_dnsDomain}/records";
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
- $record_type = ($this->_addressFamily == AF_INET6) ? "AAAA" : "A";
+ $record_type = ($this->_addressFamilyRR == AF_INET6) ? "AAAA" : "A";
// Check if a record already exists for this host.
curl_setopt($ch, CURLOPT_URL, "{$namedotcom_api}?perPage=1000");
curl_setopt($ch, CURLOPT_FORBID_REUSE, true);
@@ -955,7 +979,7 @@
case 'porkbun-v6':
// API documentation: https://api.porkbun.com/api/json/v3/documentation
$porkbun_api = "https://api.porkbun.com/api/json/v3/dns/retrieve/{$this->_dnsDomain}";
- $record_type = ($this->_addressFamily == AF_INET6) ? "AAAA" : "A";
+ $record_type = ($this->_addressFamilyRR == AF_INET6) ? "AAAA" : "A";
// Check if a record already exists for this host.
$post_data['apikey'] = $this->_dnsUser;
$post_data['secretapikey'] = $this->_dnsPass;
@@ -1003,7 +1027,7 @@
if (($record_id) &&
($this->_forceUpdateNeeded == true) &&
($this->_dnsDummyUpdateDone == false)) {
- $post_data['content'] = ($this->_addressFamily == AF_INET6) ? "fd00:d::1" : "127.0.0.1";
+ $post_data['content'] = ($this->_addressFamilyRR == AF_INET6) ? "fd00:d::1" : "127.0.0.1";
$this->_dnsDummyUpdateDone = true;
$log_message = 'Dynamic DNS %1$s (%2$s): ';
$log_message .= 'Performing forced update. ';
@@ -1265,7 +1289,7 @@
Data sent as JSON */
$needsIP = TRUE;
$server = 'https://api.godaddy.com/v1/domains/';
- $recordType = ($this->_addressFamily == AF_INET6) ? "AAAA" : "A";
+ $recordType = ($this->_addressFamilyRR == AF_INET6) ? "AAAA" : "A";
$url = $server . $this->_dnsDomain . '/records/' . $recordType . '/' . $this->_dnsHost;
$jsondata = '[{"data":"' . $this->_dnsIP . '","ttl":' . $this->_dnsTTL . '}]';
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
@@ -1636,7 +1660,7 @@
return false;
}
// Update the DNS record
- if ($this->_addressFamily == AF_INET6) {
+ if ($this->_addressFamilyRR == AF_INET6) {
$url = "https://management.azure.com" . $resourceid . "/AAAA/" . $hostname . "?api-version=2017-09-01";
$body = '{"properties":{"TTL":"' . $newttl . '", "AAAARecords":[{"ipv6Address":"' . $newip . '"}]}}';
} else {
@@ -1658,7 +1682,7 @@
case 'linode':
case 'linode-v6':
$linode_api = "https://api.linode.com/v4";
- $record_type = ($this->_addressFamily == AF_INET6) ? "AAAA" : "A";
+ $record_type = ($this->_addressFamilyRR == AF_INET6) ? "AAAA" : "A";
$record_name = $this->_dnsHost == "@" ? "" : $this->_dnsHost;
$err_prefix = gettext("Dynamic DNS") . " {$this->_dnsService} ({$this->_FQDN}): (" . gettext("Error") . ")";
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
@@ -1755,7 +1779,7 @@
// https://api.gandi.net/docs/livedns/#v5-livedns-domains-fqdn-records-rrset_name-rrset_type
// PUT overrides the existing record or creates if none exists
$gandi_api = 'https://api.gandi.net/v5/livedns/domains/';
- $record_type = ($this->_addressFamily == AF_INET6) ? "AAAA" : "A";
+ $record_type = ($this->_addressFamilyRR == AF_INET6) ? "AAAA" : "A";
$url = "{$gandi_api}{$this->_dnsDomain}/records/{$this->_dnsHost}/{$record_type}";
$headers = array(
@@ -1825,8 +1849,6 @@
$ch = curl_init();
- curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamily == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
-
curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_INTERFACE, $this->_dnsRequestIfIP);
@@ -1835,6 +1857,7 @@
switch ($this->_dnsService) {
case 'dreamhost':
case 'dreamhost-v6':
+ curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamilyRequest == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
$server = 'https://api.dreamhost.com/';
$post_data['key'] = $this->_dnsPass;
$post_data['unique_id'] = uniqid($this->_dnsHost);
@@ -1842,8 +1865,7 @@
$post_data['format'] = 'json';
$post_data['value'] = $existing_ip;
$post_data['record'] = $this->_dnsHost;
- $isv6 = ($this->_dnsService === 'dreamhost-v6');
- $post_data['type'] = $isv6 ? 'AAAA' : 'A';
+ $post_data['type'] = ($this->_addressFamilyRR == AF_INET6) ? 'AAAA' : 'A';
$port = "";
if ($this->_dnsServer) {
$server = $this->_dnsServer;
@@ -1856,6 +1878,12 @@
$remove_allowed = true;
break;
default:
+ /**
+ * When the resource record (RR) type is not specified for
+ * the removal request, it is assumed that the RR being
+ * removed is dependent on the request's IP address family.
+ */
+ curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamilyRR == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
break;
}
if ($remove_allowed) {
@@ -1886,7 +1914,7 @@
$ch = curl_init();
- curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamily == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
+ curl_setopt($ch, CURLOPT_IPRESOLVE, (($this->_addressFamilyRequest == AF_INET6) ? CURL_IPRESOLVE_V6 : CURL_IPRESOLVE_V4));
curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
@@ -1957,8 +1985,8 @@
} else {
foreach($result["data"] as $key => $row) {
if($row["record"] == $this->_dnsHost &&
- (($row["type"] == "A" && ($this->_addressFamily == AF_INET))
- || ($row["type"] == "AAAA" && ($this->_addressFamily == AF_INET6))
+ (($row["type"] == "A" && ($this->_addressFamilyRR == AF_INET))
+ || ($row["type"] == "AAAA" && ($this->_addressFamilyRR == AF_INET6))
)) {
if($row["editable"] == 0) {
log_error($status_intro . "host " . $this->_dnsHost . " is not editable.");
@@ -3040,21 +3068,19 @@
if ($successful_update == true) {
/* Write WAN IP to cache file */
- $wan_ip = dyndnsCheckIP($this->_dnsRequestIf, $this->_checkIPMode, $this->_addressFamily);
- $this->_dnsIP = $wan_ip;
- if (($this->_addressFamily == AF_INET) && $wan_ip) {
+ if ($this->_addressFamilyRR == AF_INET) {
$currentTime = time();
- notify_all_remote(sprintf(gettext('DynDNS updated IP Address for %1$s on %2$s (%3$s) to %4$s'), $this->_FQDN, convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
- log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile, $wan_ip));
- @file_put_contents($this->_cacheFile, "{$wan_ip}|{$currentTime}");
+ notify_all_remote(sprintf(gettext('DynDNS updated IP Address for %1$s on %2$s (%3$s) to %4$s'), $this->_FQDN, convert_real_interface_to_friendly_descr($this->_if), $this->_if, $this->_dnsIP));
+ log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile, $this->_dnsIP));
+ @file_put_contents($this->_cacheFile, "{$this->_dnsIP}|{$currentTime}");
} else {
@unlink($this->_cacheFile);
}
- if (($this->_addressFamily == AF_INET6) && $wan_ip) {
+ if ($this->_addressFamilyRR == AF_INET6) {
$currentTime = time();
- notify_all_remote(sprintf(gettext('DynDNS updated IPv6 Address for %1$s on %2$s (%3$s) to %4$s'), $this->_FQDN, convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
- log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile_v6, $wan_ip));
- @file_put_contents($this->_cacheFile_v6, "{$wan_ip}|{$currentTime}");
+ notify_all_remote(sprintf(gettext('DynDNS updated IPv6 Address for %1$s on %2$s (%3$s) to %4$s'), $this->_FQDN, convert_real_interface_to_friendly_descr($this->_if), $this->_if, $this->_dnsIP));
+ log_error(sprintf(gettext('phpDynDNS: updating cache file %1$s: %2$s'), $this->_cacheFile_v6, $this->_dnsIP));
+ @file_put_contents($this->_cacheFile_v6, "{$this->_dnsIP}|{$currentTime}");
} else {
@unlink($this->_cacheFile_v6);
}
@@ -3126,15 +3152,14 @@
$currentTime = time();
- $wan_ip = dyndnsCheckIP($this->_dnsRequestIf, $this->_checkIPMode, $this->_addressFamily);
- $this->_dnsIP = $wan_ip;
- if (!$wan_ip) {
+ $this->_dnsIP = dyndnsCheckIP($this->_dnsRequestIf, $this->_checkIPMode, $this->_addressFamilyRR);
+ if (!$this->_dnsIP) {
log_error(sprintf(gettext("Dynamic Dns (%s): Current WAN IP could not be determined, skipping update process."), $this->_FQDN));
return false;
}
- $log_error = sprintf(gettext('Dynamic Dns (%1$s): Current WAN IP: %2$s'), $this->_FQDN, $wan_ip) . " ";
+ $log_error = sprintf(gettext('Dynamic Dns (%1$s): Current WAN IP: %2$s'), $this->_FQDN, $this->_dnsIP) . " ";
- if (($this->_addressFamily == AF_INET6)) {
+ if (($this->_addressFamilyRR == AF_INET6)) {
if (file_exists($this->_cacheFile_v6)) {
$contents = file_get_contents($this->_cacheFile_v6);
list($cacheIP, $cacheTime) = explode('|', $contents);
@@ -3175,10 +3200,10 @@
$needs_updating = FALSE;
/* lets determine if the item needs updating */
- if ($cacheIP != $wan_ip) {
+ if ($cacheIP != $this->_dnsIP) {
$needs_updating = true;
$update_reason = gettext("Dynamic Dns: cacheIP != wan_ip. Updating.") . " ";
- $update_reason .= sprintf(gettext('Cached IP: %1$s WAN IP: %2$s'), $cacheIP, $wan_ip) . " ";
+ $update_reason .= sprintf(gettext('Cached IP: %1$s WAN IP: %2$s'), $cacheIP, $this->_dnsIP) . " ";
}
if (($currentTime - $cacheTime) > $maxCacheAgeSecs) {
$needs_updating = true;
diff --git a/src/usr/local/www/services_dyndns.php b/src/usr/local/www/services_dyndns.php
index 94a96f1833..372ff7b325 100644
--- a/src/usr/local/www/services_dyndns.php
+++ b/src/usr/local/www/services_dyndns.php
@@ -114,7 +114,7 @@ foreach (config_get_path("dyndnses/dyndns", []) as $dyndns):
$filename = "{$g['conf_path']}/dyndns_{$dyndns['interface']}{$dyndns['type']}" . escapeshellarg($hostname) . "{$dyndns['id']}.cache";
$filename_v6 = "{$g['conf_path']}/dyndns_{$dyndns['interface']}{$dyndns['type']}" . escapeshellarg($hostname) . "{$dyndns['id']}_v6.cache";
if (file_exists($filename)) {
- $ipaddr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'));
+ $ipaddr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'), AF_INET);
$cached_ip_s = explode("|", file_get_contents($filename));
$cached_ip = $cached_ip_s[0];
@@ -128,7 +128,7 @@ foreach (config_get_path("dyndnses/dyndns", []) as $dyndns):
$icon_title = "Failed";
}
} else if (file_exists($filename_v6)) {
- $ipv6addr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'));
+ $ipv6addr = dyndnsCheckIP($dyndns['interface'], array_get_path($dyndns, 'check_ip_mode'), AF_INET6);
$cached_ipv6_s = explode("|", file_get_contents($filename_v6));
$cached_ipv6 = $cached_ipv6_s[0];
diff --git a/src/usr/local/www/services_dyndns_edit.php b/src/usr/local/www/services_dyndns_edit.php
index 27cbb9877d..4648282906 100644
--- a/src/usr/local/www/services_dyndns_edit.php
+++ b/src/usr/local/www/services_dyndns_edit.php
@@ -255,7 +255,18 @@ if ($_POST['save'] || $_POST['force']) {
}
$dyndns['curl_proxy'] = $_POST['curl_proxy'] ? true : false;
$dyndns['descr'] = $_POST['descr'];
- $dyndns['force'] = isset($_POST['force']);
+
+ /**
+ * An update is forced when the interface changes because the IP
+ * for the new interface may already be cached; if that cache
+ * contains the same IP address as the new interface then the
+ * record is not updated.
+ */
+ if (isset($_POST['force']) || $dup || ($_POST['interface'] != $this_dyndns_config['interface'])) {
+ $dyndns['force'] = true;
+ } else {
+ $dyndns['force'] = false;
+ }
if ($dyndns['username'] == "none") {
$dyndns['username'] = "";
Updated by Marcos M 2 months ago
- Subject changed from Dynamic DNS IPv6 to Dynamic DNS IPv6 tries to use IPv4 address
- Status changed from In Progress to Feedback
- Target version set to 2.8.0
- % Done changed from 0 to 100
- Plus Target Version set to 25.03
- Release Notes changed from Default to Force Exclusion
- Affected Version set to 2.8.0