Regression #16045
closedDynamic DNS IPv6 tries to use IPv4 address
Added by Bart Schapendonk 11 months ago. Updated 7 months 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 11 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 11 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 11 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 11 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
Updated by Jim Pingle 7 months ago
- Plus Target Version changed from 25.03 to 25.07