Merge branch 'ddclient:master' into feature_provider_ydns

This commit is contained in:
Jesse 2023-10-23 08:52:44 +02:00 committed by GitHub
commit 31fe115da0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 70 additions and 44 deletions

View file

@ -3,11 +3,17 @@
This document describes notable changes. For details, see the [source code
repository history](https://github.com/ddclient/ddclient/commits/master).
## 2023-XX-XX v3.11.0_1
## 20XX-XX-XX v3.11.1_0 (WIP)
## 2023-10-21 v3.11.0
This version is the same as v3.11.0_1 (except for the updated version number in the code).
Refer to [v3.11 release plan discussions](https://github.com/ddclient/ddclient/issues/552) for the reasons.
## 2023-10-15 v3.11.0_1
### Breaking changes
* ddclient now requires curl.
* ddclient now requires curl. The Perl modules IO::Socket::IP and IO::Socket::SSL are no longer used.
* ddclient no longer ships any example files for init systems that use `/etc/init.d`.
This was done because those files where effectively unmaintained, untested by the developers and only updated by downstream distros.
If you where relying on those files, please copy them into your packaging.

View file

@ -19,6 +19,7 @@ Dynamic DNS services currently supported include:
* [ChangeIP](https://www.changeip.com)
* [CloudFlare](https://www.cloudflare.com)
* [ClouDNS](https://www.cloudns.net)
* [DigitalOcean](https://www.digitalocean.com/)
* [dinahosting](https://dinahosting.com)
* [DonDominio](https://www.dondominio.com)
* [DNS Made Easy](https://dnsmadeeasy.com)

View file

@ -1,5 +1,5 @@
AC_PREREQ([2.63])
AC_INIT([ddclient], [3.11.0])
AC_INIT([ddclient], [3.11.1_0])
AC_CONFIG_SRCDIR([ddclient.in])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])

View file

@ -535,9 +535,9 @@ my %variables = (
'dnsexit2-common-defaults' => {
'ssl' => setv(T_BOOL, 0, 0, 1, undef),
'server' => setv(T_FQDNP, 1, 0, 'api.dnsexit.com', undef),
'path' => setv(T_STRING, 0, 1, '/dns/', undef),
'record-type' => setv(T_STRING, 1, 0, 'A', undef),
'path' => setv(T_STRING, 0, 0, '/dns/', undef),
'ttl' => setv(T_NUMBER, 1, 0, 5, 0),
'zone' => setv(T_STRING, 0, 0, undef, undef)
},
'regfishde-common-defaults' => {
'server' => setv(T_FQDNP, 1, 0, 'dyndns.regfish.de', undef),
@ -4060,24 +4060,29 @@ sub nic_dnsexit2_examples {
return <<"EoEXAMPLE";
o 'dnsexit2'
The 'dnsexit2' protocol is the new API protocol used by the dynamic hostname services
of the 'DNSExit' dns services. This is currently used by the free
dynamic DNS service offered by www.dnsexit.com.
The 'dnsexit2' protocol is the updated protocol for the (free) dynamic hostname services
of 'DNSExit' (www.dnsexit.com). Their API is accepting JSON payload.
Configuration variables applicable to the 'dnsexit2' protocol are:
protocol=dnsexit2 ##
password=YourAPIKey ## API Key of your account.
server=api.dnsexit.com ## defaults to api.dnsexit.com.
path=/dns/ ## defaults to /dns/.
record-type=A ## defaults to A record.
ttl=5 ## defaults to 5 minutes.
zone='' ## defaults to empty, which assumes the zone is equal to the fully.qualified.host (is root of your DNSExit domain).
fully.qualified.host ## the host registered with the service.
Example ${program}.conf file entries:
## single host update
protocol=dnsexit2
password=YourAPIKey
fully.qualified.host
yourown.publicvm.com
## two hosts (which must be) on the same zone
protocol=dnsexit2
password=YourAPIKey
zone=yourown.publicvm.com
host1.yourown.publicvm.com,host2.yourown.publicvm.com
EoEXAMPLE
}
@ -4091,7 +4096,7 @@ EoEXAMPLE
sub nic_dnsexit2_update {
debug("\nnic_dnsexit2_update -------------------");
## Update each configured host
## Update each configured host (hosts cannot be grouped on this API)
foreach my $h (@_) {
# All the known status
my %status = (
@ -4104,25 +4109,45 @@ sub nic_dnsexit2_update {
'6' => [ 'error', 'System Error. Our system problem. May not be your problem. Contact our support if you got such error.' ],
'7' => [ 'error', 'Error getting post data. Our server has problem to receive your JSON posting.' ],
);
my $ip = delete $config{$h}{'wantip'};
info("Going to update IP address to %s for %s.", $ip, $h);
my $ipv4 = delete $config{$h}{'wantipv4'};
my $ipv6 = delete $config{$h}{'wantipv6'};
# Updates for ipv4 and ipv6 need to be combined in a single API call, create Hash of Arrays for tracking
my %total_payload;
foreach my $ip ($ipv4, $ipv6){
next if (!$ip);
my $ipv = ($ip eq ($ipv6 // '')) ? '6' : '4';
my $type = ($ip eq ($ipv6 // '')) ? 'AAAA' : 'A';
info("Going to update IPv$ipv address to %s for %s.", $ip, $h);
$config{$h}{'status-ipv$ipv'} = 'failed';
# One key per ipv (4 or 6)
my %payload = (name => $h, type => $type, content => $ip, ttl => $config{$h}{'ttl'});
@total_payload{$ipv} = \%payload;
};
# Set the URL of the API endpoint
my $url = "https://$config{$h}{'server'}$config{$h}{'path'}";
# Set JSON payload
my $data = encode_json({
apikey => $config{$h}{'password'},
domain => $h,
update => {
type => $config{$h}{'record-type'},
name => $h,
content => $ip,
ttl => $config{$h}{'ttl'}},
});
# Set additional headers
my $header = "Content-Type: application/json\n";
$header .= "Accept: application/json";
my $header = "Content-Type: application/json\nAccept: application/json";
# Set the zone if empty
if ( not defined $config{$h}{'zone'}){
debug("Zone not defined, setting to default hostname: %s", $h);
$config{$h}{'zone'} = $h
} else {
debug("Zone is: %s", $config{$h}{'zone'});
}
# Build total JSON payload
my @payload_values = values %total_payload;
my $data = encode_json({
apikey => $config{$h}{'password'},
domain => $config{$h}{'zone'},
update => \@payload_values
});
# Make the call
my $reply = geturl(
@ -4130,32 +4155,27 @@ sub nic_dnsexit2_update {
url => $url,
headers => $header,
method => 'POST',
data => $data,
data => $data
);
# No reply, declare as failed
if (!defined($reply) || !$reply) {
unless ($reply && header_ok($h, $reply)){
failed("updating %s: Could not connect to %s%s.", $h, $config{$h}{'server'}, $config{$h}{'path'});
$config{$h}{'status'} = 'failed';
last;
};
# Reply found
debug("%s", $reply);
# $ok is mandatory?
my $ok = header_ok($h, $reply);
# Extract the HTTP response code
(my $http_status) = ($reply =~ m%^s*HTTP/.*\s+(\d+)%i);
debug("HTTP response code: %s", $http_status);
# If not 200, bail
if ( $http_status != "200"){
failed("Failed to update Host\n%s to IP:%s", $h, $ip);
if ( $http_status ne '200' ){
failed("Failed to update Host\n%s", $h);
failed("HTTP response code\n%s", $http_status);
failed("Full reply\n%s", $reply) unless opt('verbose');
$config{$h}{'status'} = 'failed';
last;
next;
}
# Strip HTTP response headers
@ -4192,31 +4212,30 @@ sub nic_dnsexit2_update {
# Handle statuses
if ($status eq 'good') {
$config{$h}{'ip'} = $ip;
$config{$h}{'mtime'} = $now;
$config{$h}{'status'} = 'good';
success("%s", $message);
success("Updated %s successfully to IP address %s at time %s", $h, $ip, prettytime($config{$h}{'mtime'}));
my $tracked_ipv;
foreach $tracked_ipv ( keys %total_payload ){
$config{$h}{"ipv$tracked_ipv"} = $total_payload{$tracked_ipv}{content};
$config{$h}{"status-ipv$tracked_ipv"} = 'good';
success("%s", $message);
success("Updated %s successfully to IPv$tracked_ipv address %s at time %s", $h, $total_payload{$tracked_ipv}{content}, prettytime($config{$h}{'mtime'}));
}
} elsif ($status eq 'warning') {
warning("%s", $message);
warning("Server response: %s", $srv_message);
} elsif ($status =~ m'^(badauth|error)$') {
failed("%s", $message);
failed("Server response: %s", $srv_message);
$config{$h}{'status'} = 'failed';
} else {
failed("This should not be possible");
$config{$h}{'status'} = 'failed';
}
} else {
failed("Status code %s is unknown!", $response->{'code'});
$config{$h}{'status'} = 'failed';
}
} else {
failed("Did not receive expected \"code\" and \"message\" keys in server response.");
failed("Response:");
failed("%s", $response);
$config{$h}{'status'} = 'failed';
}
}
}