Merge pull request #709 from rhansen/dyndns2
`dyndns2` readability improvements, take 2
This commit is contained in:
commit
f6e13f8003
3 changed files with 77 additions and 96 deletions
|
@ -34,6 +34,13 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
|||
* Deprecated built-in web IP discovery services are not listed in the output
|
||||
of `--list-web-services`.
|
||||
[#682](https://github.com/ddclient/ddclient/pull/682)
|
||||
* `dyndns2`: Support for "wait" response lines has been removed. The Dyn
|
||||
documentation does not mention such responses, and the code to handle them,
|
||||
untouched since at least 2006, is believed to be obsolete.
|
||||
[#709](https://github.com/ddclient/ddclient/pull/709)
|
||||
* `dyndns2`: The obsolete `static` and `custom` options have been removed.
|
||||
Setting the options may produce a warning.
|
||||
[#709](https://github.com/ddclient/ddclient/pull/709)
|
||||
|
||||
### New features
|
||||
|
||||
|
|
|
@ -81,26 +81,6 @@ pid=@runstatedir@/ddclient.pid # record PID in file.
|
|||
# protocol=dyndns2 \
|
||||
# your-dynamic-host.dyndns.org
|
||||
|
||||
##
|
||||
## dyndns.org static addresses
|
||||
##
|
||||
## (supports variables: wildcard,mx,backupmx)
|
||||
##
|
||||
# static=yes, \
|
||||
# server=members.dyndns.org, \
|
||||
# protocol=dyndns2 \
|
||||
# your-static-host.dyndns.org
|
||||
|
||||
##
|
||||
## dyndns.org custom addresses
|
||||
##
|
||||
## (supports variables: wildcard,mx,backupmx)
|
||||
##
|
||||
# custom=yes, \
|
||||
# server=members.dyndns.org, \
|
||||
# protocol=dyndns2 \
|
||||
# your-domain.top-level,your-other-domain.top-level
|
||||
|
||||
##
|
||||
## ZoneEdit (zoneedit.com)
|
||||
##
|
||||
|
|
126
ddclient.in
126
ddclient.in
|
@ -709,7 +709,6 @@ our %variables = (
|
|||
'dyndns-common-defaults' => {
|
||||
'backupmx' => setv(T_BOOL, 0, 1, 0, undef),
|
||||
'mx' => setv(T_OFQDN, 0, 1, undef, undef),
|
||||
'static' => setv(T_BOOL, 0, 1, 0, undef),
|
||||
'wildcard' => setv(T_BOOL, 0, 1, 0, undef),
|
||||
},
|
||||
);
|
||||
|
@ -848,6 +847,7 @@ our %protocols = (
|
|||
'variables' => {
|
||||
%{$variables{'protocol-common-defaults'}},
|
||||
%{$variables{'dyndns-common-defaults'}},
|
||||
'static' => setv(T_BOOL, 0, 1, 0, undef),
|
||||
},
|
||||
},
|
||||
'dyndns2' => {
|
||||
|
@ -857,7 +857,6 @@ our %protocols = (
|
|||
'variables' => {
|
||||
%{$variables{'protocol-common-defaults'}},
|
||||
%{$variables{'dyndns-common-defaults'}},
|
||||
'custom' => setv(T_BOOL, 0, 1, 0, undef),
|
||||
'script' => setv(T_STRING, 0, 1, '/nic/update', undef),
|
||||
},
|
||||
},
|
||||
|
@ -4015,8 +4014,6 @@ Configuration variables applicable to the 'dyndns2' protocol are:
|
|||
server=fqdn.of.service ## defaults to members.dyndns.org
|
||||
script=/path/to/script ## defaults to /nic/update
|
||||
backupmx=no|yes ## indicates that this host is the primary MX for the domain.
|
||||
static=no|yes ## indicates that this host has a static IP address.
|
||||
custom=no|yes ## indicates that this host is a 'custom' top-level domain name.
|
||||
mx=any.host.domain ## a host MX'ing for this host definition.
|
||||
wildcard=no|yes ## add a DNS wildcard CNAME record that points to <host>
|
||||
login=service-login ## login name and password registered with the service
|
||||
|
@ -4050,7 +4047,6 @@ EoEXAMPLE
|
|||
######################################################################
|
||||
sub nic_dyndns2_update {
|
||||
debug("\nnic_dyndns2_update -------------------");
|
||||
my @groups = group_hosts_by(\@_, qw(login password server script static custom wildcard mx backupmx wantipv4 wantipv6));
|
||||
my %errors = (
|
||||
'badauth' => 'Bad authorization (username or password)',
|
||||
'badsys' => 'The system parameter given was not valid',
|
||||
|
@ -4064,7 +4060,18 @@ sub nic_dyndns2_update {
|
|||
'dnserr' => 'System error: DNS error encountered. Contact support@dyndns.org',
|
||||
'nochg' => 'No update required; unnecessary attempts to change to the current address are considered abusive',
|
||||
);
|
||||
for my $group (@groups) {
|
||||
my @group_by_attrs = qw(
|
||||
backupmx
|
||||
login
|
||||
mx
|
||||
password
|
||||
script
|
||||
server
|
||||
wantipv4
|
||||
wantipv6
|
||||
wildcard
|
||||
);
|
||||
for my $group (group_hosts_by(\@_, @group_by_attrs)) {
|
||||
my @hosts = @{$group->{hosts}};
|
||||
my %groupcfg = %{$group->{cfg}};
|
||||
my $hosts = join(',', @hosts);
|
||||
|
@ -4072,21 +4079,9 @@ sub nic_dyndns2_update {
|
|||
my $ipv6 = $groupcfg{'wantipv6'};
|
||||
delete $config{$_}{'wantipv4'} for @hosts;
|
||||
delete $config{$_}{'wantipv6'} for @hosts;
|
||||
info("setting IPv4 address to %s for %s", $ipv4, $hosts) if $ipv4;
|
||||
info("setting IPv6 address to %s for %s", $ipv6, $hosts) if $ipv6;
|
||||
verbose("UPDATE:", "updating %s", $hosts);
|
||||
my $url = "$groupcfg{'server'}$groupcfg{'script'}?system=";
|
||||
if ($groupcfg{'custom'}) {
|
||||
warning("updating %s: 'custom' and 'static' may not be used together. ('static' ignored)", $hosts)
|
||||
if $groupcfg{'static'};
|
||||
$url .= 'custom';
|
||||
} elsif ($groupcfg{'static'}) {
|
||||
$url .= 'statdns';
|
||||
} else {
|
||||
$url .= 'dyndns';
|
||||
}
|
||||
$url .= "&hostname=$hosts";
|
||||
$url .= "&myip=";
|
||||
info("$hosts: setting IPv4 address to $ipv4") if $ipv4;
|
||||
info("$hosts: setting IPv6 address to $ipv6") if $ipv6;
|
||||
my $url = "$groupcfg{'server'}$groupcfg{'script'}?hostname=$hosts&myip=";
|
||||
$url .= $ipv4 if $ipv4;
|
||||
if ($ipv6) {
|
||||
$url .= "," if $ipv4;
|
||||
|
@ -4105,65 +4100,64 @@ sub nic_dyndns2_update {
|
|||
password => $groupcfg{'password'},
|
||||
) // '';
|
||||
if ($reply eq '') {
|
||||
failed("updating %s: Could not connect to %s.", $hosts, $groupcfg{'server'});
|
||||
failed("$hosts: Could not connect to $groupcfg{'server'}");
|
||||
next;
|
||||
}
|
||||
next if !header_ok($hosts, $reply);
|
||||
my @reply = split /\n/, $reply;
|
||||
my $state = 'header';
|
||||
# Some services can return 200 OK even if there is an error (e.g., bad authentication,
|
||||
# updates too frequent) so the body of the response must also be checked.
|
||||
(my $body = $reply) =~ s/^.*?\n\n//s;
|
||||
my @reply = split(qr/\n/, $body);
|
||||
if (!@reply) {
|
||||
failed("$hosts: Could not connect to $groupcfg{'server'}");
|
||||
next;
|
||||
}
|
||||
# From <https://help.dyn.com/remote-access-api/return-codes/>:
|
||||
#
|
||||
# If updating multiple hostnames, hostname-specific return codes are given one per line,
|
||||
# in the same order as the hostnames were specified. Return codes indicating a failure
|
||||
# with the account or the system are given only once.
|
||||
#
|
||||
# TODO: There is no mention of what happens if multiple IP addresses are supplied (e.g.,
|
||||
# IPv4 and IPv6) for a host. If one address fails to update and the other doesn't, is that
|
||||
# one error status line? An error status line and a success status line? Or is an update
|
||||
# considered to be all-or-nothing and the status applies to the operation as a whole? If
|
||||
# the IPv4 address changes but not the IPv6 address does that result in a status of "good"
|
||||
# because the set of addresses for a host changed even if a subset did not?
|
||||
#
|
||||
# TODO: The logic below applies the last line's status to all hosts. Change it to apply
|
||||
# each status to its corresponding host.
|
||||
for my $line (@reply) {
|
||||
if ($state eq 'header') {
|
||||
$state = 'body';
|
||||
} elsif ($state eq 'body') {
|
||||
$state = 'results' if $line eq '';
|
||||
} elsif ($state =~ /^results/) {
|
||||
$state = 'results2';
|
||||
# bug #10: some dyndns providers does not return the IP so
|
||||
# we can't use the returned IP
|
||||
my ($status, $returnedips) = split / /, lc $line;
|
||||
# The IP address normally comes after the status, but we ignore it. We could compare
|
||||
# it with the expected address and mark the update as failed if it differs, but (1)
|
||||
# some services do not return the IP; and (2) comparison is brittle (e.g.,
|
||||
# 192.000.002.001 vs. 192.0.2.1) and false errors could cause high load on the service
|
||||
# (an update attempt every min-error-interval instead of every max-interval).
|
||||
(my $status = $line) =~ s/ .*$//;
|
||||
if ($status eq 'nochg') {
|
||||
warning("$hosts: $status: $errors{$status}");
|
||||
$status = 'good';
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
}
|
||||
if ($status eq 'good') {
|
||||
if ($status ne 'good') {
|
||||
if (exists($errors{$status})) {
|
||||
failed("$hosts: $status: $errors{$status}");
|
||||
} else {
|
||||
failed("$hosts: unexpected status: $line");
|
||||
}
|
||||
next;
|
||||
}
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
}
|
||||
success("updating %s: %s: IPv4 address set to %s", $hosts, $status, $ipv4) if $ipv4;
|
||||
success("updating %s: %s: IPv6 address set to %s", $hosts, $status, $ipv6) if $ipv6;
|
||||
} elsif (exists $errors{$status}) {
|
||||
if ($status eq 'nochg') {
|
||||
warning("updating %s: %s: %s", $hosts, $status, $errors{$status});
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
success("$hosts: IPv4 address set to $ipv4") if $ipv4;
|
||||
success("$hosts: IPv6 address set to $ipv6") if $ipv6;
|
||||
}
|
||||
} else {
|
||||
failed("updating %s: %s: %s", $hosts, $status, $errors{$status});
|
||||
}
|
||||
} elsif ($status =~ /w(\d+)(.)/) {
|
||||
my ($wait, $units) = ($1, lc $2);
|
||||
my ($sec, $scale) = ($wait, 1);
|
||||
($scale, $units) = (1, 'seconds') if $units eq 's';
|
||||
($scale, $units) = (60, 'minutes') if $units eq 'm';
|
||||
($scale, $units) = (60*60, 'hours') if $units eq 'h';
|
||||
$sec = $wait * $scale;
|
||||
for my $h (@hosts) {
|
||||
$config{$h}{'wtime'} = $now + $sec;
|
||||
}
|
||||
warning("updating %s: %s: wait %s %s before further updates", $hosts, $status, $wait, $units);
|
||||
} else {
|
||||
failed("updating %s: unexpected status (%s)", $hosts, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
failed("updating %s: Could not connect to %s.", $hosts, $groupcfg{'server'})
|
||||
if $state ne 'results2';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue