Merge pull request #184 from rhansen/freedns
Redo freedns.afraid.org protocol to fix several bugs
This commit is contained in:
commit
58c6570dde
2 changed files with 80 additions and 39 deletions
|
@ -14,8 +14,15 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
||||||
|
|
||||||
./autogen && ./configure && make && make check && make install
|
./autogen && ./configure && make && make check && make install
|
||||||
|
|
||||||
|
* The `freedns` protocol (for https://freedns.afraid.org) now supports IPv6
|
||||||
|
addresses.
|
||||||
|
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
|
|
||||||
|
* Minor `freedns` protocol fixes, including:
|
||||||
|
* You can now update an address that differs from the system's own.
|
||||||
|
* If multiple hosts are defined and one fails, ddclient will no longer
|
||||||
|
skip the remaining hosts.
|
||||||
* Fixed a regression introduced in v3.9.0 that caused
|
* Fixed a regression introduced in v3.9.0 that caused
|
||||||
`use=ip,ip=<ipv4-address>` to fail.
|
`use=ip,ip=<ipv4-address>` to fail.
|
||||||
* "true" is now accepted as a boolean value.
|
* "true" is now accepted as a boolean value.
|
||||||
|
|
|
@ -3911,62 +3911,96 @@ EoEXAMPLE
|
||||||
######################################################################
|
######################################################################
|
||||||
## nic_freedns_update
|
## nic_freedns_update
|
||||||
##
|
##
|
||||||
## written by John Haney
|
## API v1 documented at http://freedns.afraid.org/api/
|
||||||
##
|
##
|
||||||
## based on http://freedns.afraid.org/api/
|
## An update requires two steps. The first is to get a list of records from:
|
||||||
## needs this url to update:
|
## http://freedns.afraid.org/api/?action=getdyndns&v=2&sha=<sha1sum of login|password>
|
||||||
## http://freedns.afraid.org/api/?action=getdyndns&sha=<sha1sum of login|password>
|
## The returned list looks like:
|
||||||
## This returns a list of host|currentIP|updateURL lines.
|
|
||||||
## Pick the line that matches myhost, and fetch the URL.
|
|
||||||
## word 'Updated' for success, 'fail' for failure.
|
|
||||||
##
|
##
|
||||||
|
## hostname1.example.com|1.2.3.4|http://example/update/url1
|
||||||
|
## hostname1.example.com|dead::beef|http://example/update/url2
|
||||||
|
## hostname2.example.com|5.6.7.8|http://example/update/url3
|
||||||
|
## hostname2.example.com|9.10.11.12|http://example/update/url4
|
||||||
|
## hostname3.example.com|cafe::f00d|http://example/update/url5
|
||||||
|
##
|
||||||
|
## The record's columns are separated by '|'. The first is the hostname, the second is the current
|
||||||
|
## address, and the third is the record-specific update URL. There can be multiple records for the
|
||||||
|
## same host, and they can even have the same address type. Any record can be updated to hold
|
||||||
|
## either type of address (e.g., if given an IPv6 address the record will automatically become an
|
||||||
|
## AAAA record).
|
||||||
|
##
|
||||||
|
## The second step is to visit the appropriate record's update URL with
|
||||||
|
## ?address=<ipv4-or-ipv6-address> appended. "Updated" in the result means success, "fail" means
|
||||||
|
## failure.
|
||||||
######################################################################
|
######################################################################
|
||||||
sub nic_freedns_update {
|
sub nic_freedns_update {
|
||||||
|
|
||||||
|
|
||||||
debug("\nnic_freedns_update -------------------");
|
debug("\nnic_freedns_update -------------------");
|
||||||
|
# Separate the records that are currently holding IPv4 addresses from the records that are
|
||||||
## First get the list of updatable hosts
|
# currently holding IPv6 addresses so that we can avoid switching a record to a different
|
||||||
my $url;
|
# address type.
|
||||||
$url = "http://$config{$_[0]}{'server'}/api/?action=getdyndns&sha=" . &sha1_hex("$config{$_[0]}{'login'}|$config{$_[0]}{'password'}");
|
my %recs_ipv4;
|
||||||
|
my %recs_ipv6;
|
||||||
|
my $url_tmpl = "http://$config{$_[0]}{'server'}/api/?action=getdyndns&v=2&sha=<credentials>";
|
||||||
|
my $creds = sha1_hex("$config{$_[0]}{'login'}|$config{$_[0]}{'password'}");
|
||||||
|
(my $url = $url_tmpl) =~ s/<credentials>/$creds/;
|
||||||
my $reply = geturl({ proxy => opt('proxy'), url => $url });
|
my $reply = geturl({ proxy => opt('proxy'), url => $url });
|
||||||
if (!defined($reply) || !$reply || !header_ok($_[0], $reply)) {
|
my $record_list_error = '';
|
||||||
failed("updating %s: Could not connect to %s for site list.", $_[0], $url);
|
if ($reply && header_ok($_[0], $reply)) {
|
||||||
return;
|
$reply =~ s/^.*?\n\n//s; # Strip the headers.
|
||||||
|
for (split("\n", $reply)) {
|
||||||
|
my @rec = split(/\|/);
|
||||||
|
next if ($#rec < 2);
|
||||||
|
my $recs = is_ipv6($rec[1]) ? \%recs_ipv6 : \%recs_ipv4;
|
||||||
|
$recs->{$rec[0]} = \@rec;
|
||||||
|
debug("host: %s, current address: %s, update URL: %s", @rec);
|
||||||
}
|
}
|
||||||
my @lines = split("\n", $reply);
|
if (keys(%recs_ipv4) + keys(%recs_ipv6) == 0) {
|
||||||
my %freedns_hosts;
|
chomp($reply);
|
||||||
grep {
|
$record_list_error = "failed to get record list from $url_tmpl: $reply";
|
||||||
my @rec = split(/\|/, $_);
|
|
||||||
$freedns_hosts{$rec[0]} = \@rec if ($#rec > 0);
|
|
||||||
} @lines;
|
|
||||||
if (!keys %freedns_hosts) {
|
|
||||||
failed("Could not get freedns update URLs from %s", $config{$_[0]}{'server'});
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
## update each configured host
|
} else {
|
||||||
|
$record_list_error = "failed to get record list from $url_tmpl";
|
||||||
|
}
|
||||||
|
|
||||||
foreach my $h (@_) {
|
foreach my $h (@_) {
|
||||||
if (!$h) { next }
|
if (!$h) { next }
|
||||||
my $ip = delete $config{$h}{'wantip'};
|
my $ip = delete $config{$h}{'wantip'};
|
||||||
info("setting IP address to %s for %s", $ip, $h);
|
|
||||||
verbose("UPDATE:", "updating %s", $h);
|
|
||||||
|
|
||||||
if ($ip eq $freedns_hosts{$h}->[1]) {
|
info("%s: setting IP address to %s", $h, $ip);
|
||||||
|
|
||||||
|
if ($record_list_error ne '') {
|
||||||
|
$config{$h}{'status'} = 'failed';
|
||||||
|
failed("updating %s: %s", $h, $record_list_error);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
# If there is a record with matching type then update it, otherwise let
|
||||||
|
# freedns convert the record to the desired type.
|
||||||
|
my $rec = is_ipv6($ip)
|
||||||
|
? ($recs_ipv6{$h} // $recs_ipv4{$h})
|
||||||
|
: ($recs_ipv4{$h} // $recs_ipv6{$h});
|
||||||
|
if (!defined($rec)) {
|
||||||
|
$config{$h}{'status'} = 'failed';
|
||||||
|
failed("updating %s: host record does not exist", $h);
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ip eq $rec->[1]) {
|
||||||
$config{$h}{'ip'} = $ip;
|
$config{$h}{'ip'} = $ip;
|
||||||
$config{$h}{'mtime'} = $now;
|
$config{$h}{'mtime'} = $now;
|
||||||
$config{$h}{'status'} = 'good';
|
$config{$h}{'status'} = 'good';
|
||||||
success("update not necessary %s: good: IP address already set to %s", $h, $ip);
|
success("update not necessary %s: good: IP address already set to %s", $h, $ip)
|
||||||
|
if (!$daemon || opt('verbose'));
|
||||||
} else {
|
} else {
|
||||||
my $reply = geturl({proxy => opt('proxy'), url => $freedns_hosts{$h}->[2] });
|
my $url = $rec->[2] . "&address=" . $ip;
|
||||||
if (!defined($reply) || !$reply) {
|
debug("Update: %s", $url);
|
||||||
failed("updating %s: Could not connect to %s.", $h, $freedns_hosts{$h}->[2]);
|
my $reply = geturl({proxy => opt('proxy'), url => $url });
|
||||||
last;
|
if (!defined($reply) || !$reply || !header_ok($h, $reply)) {
|
||||||
}
|
|
||||||
if (!header_ok($h, $reply)) {
|
|
||||||
$config{$h}{'status'} = 'failed';
|
$config{$h}{'status'} = 'failed';
|
||||||
last;
|
failed("updating %s: Could not connect to %s.", $h, $url);
|
||||||
|
next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$reply =~ s/^.*?\n\n//s; # Strip the headers.
|
||||||
if ($reply =~ /Updated.*$h.*to.*$ip/) {
|
if ($reply =~ /Updated.*$h.*to.*$ip/) {
|
||||||
$config{$h}{'ip'} = $ip;
|
$config{$h}{'ip'} = $ip;
|
||||||
$config{$h}{'mtime'} = $now;
|
$config{$h}{'mtime'} = $now;
|
||||||
|
@ -3974,7 +4008,7 @@ sub nic_freedns_update {
|
||||||
success("updating %s: good: IP address set to %s", $h, $ip);
|
success("updating %s: good: IP address set to %s", $h, $ip);
|
||||||
} else {
|
} else {
|
||||||
$config{$h}{'status'} = 'failed';
|
$config{$h}{'status'} = 'failed';
|
||||||
warning("SENT: %s", $freedns_hosts{$h}->[2]) unless opt('verbose');
|
warning("SENT: %s", $url) unless opt('verbose');
|
||||||
warning("REPLIED: %s", $reply);
|
warning("REPLIED: %s", $reply);
|
||||||
failed("updating %s: Invalid reply.", $h);
|
failed("updating %s: Invalid reply.", $h);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue