From f0270e4940b7f28d551174d8a6e967d2f49368ea Mon Sep 17 00:00:00 2001 From: Reuben Thomas Date: Wed, 12 May 2021 20:45:28 +0100 Subject: [PATCH] Add dnsexit support (based on #52) (#311) * Patch in dnsexit support Based on patch from here https://sourceforge.net/p/ddclient/discussion/399428/thread/04e23ee6/ hacked back in. * dnsexit: check for valid responses that mean 'failure' (from @truesalo) Co-authored-by: sreknob --- README.md | 1 + ddclient.conf.in | 7 +++ ddclient.in | 125 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+) diff --git a/README.md b/README.md index bd0cf62..e39292f 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Dynamic DNS services currently supported include: ClouDNS - See https://www.cloudns.net dinahosting - See https://dinahosting.com Gandi - See https://gandi.net + dnsexit - See https://dnsexit.com/ for details DDclient now supports many of cable/dsl broadband routers. diff --git a/ddclient.conf.in b/ddclient.conf.in index 33ab408..5144c3a 100644 --- a/ddclient.conf.in +++ b/ddclient.conf.in @@ -302,3 +302,10 @@ ssl=yes # use ssl-support. Works with # login=myusername, \ # password=mypassword \ # myhost.mydomain.com + +## dnsexit (www.dnsexit.com) +## +#protocol=dnsexit, \ +#login=myusername, \ +#password=mypassword, \ +#subdomain-1.domain.com,subdomain-2.domain.com diff --git a/ddclient.in b/ddclient.in index c47a538..c7cf57d 100755 --- a/ddclient.in +++ b/ddclient.in @@ -523,6 +523,12 @@ my %variables = ( 'static' => setv(T_BOOL, 0, 1, 0, undef), 'wildcard' => setv(T_BOOL, 0, 1, 0, undef), }, + 'dnsexit-common-defaults' => { + 'ssl' => setv(T_BOOL, 0, 0, 0, undef), + 'server' => setv(T_FQDNP, 1, 0, 'update.dnsexit.com', undef), + 'script' => setv(T_STRING, 0, 1, '/RemoteUpdate.sv', undef), + 'min-error-interval' => setv(T_DELAY, 0, 0, interval('8m'), 0), + }, ); my %services = ( 'changeip' => { @@ -820,6 +826,15 @@ my %services = ( 'zone' => setv(T_OFQDN, 0, 0, undef, undef), }, }, + 'dnsexit' => { + 'updateable' => undef, + 'update' => \&nic_dnsexit_update, + 'examples' => \&nic_dnsexit_examples, + 'variables' => merge( + $variables{'dnsexit-common-defaults'}, + $variables{'service-common-defaults'}, + ), + }, ); $variables{'merged'} = { map({ %{$services{$_}{'variables'}} } keys(%services)), @@ -4040,7 +4055,117 @@ sub nic_dyndns2_update { } } +###################################################################### +## nic_dnsexit_examples +###################################################################### +sub nic_dnsexit_examples { + return <<"EoEXAMPLE"; +o 'dnsexit' +The 'dnsexit' protocol is the 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. + +Configuration variables applicable to the 'dnsexit' protocol are: + ssl=no ## turn off ssl + protocol=dnsexit ## + server=update.dnsexit.com ## defaults to update.dnsexit.com + use=web ## defaults to web + web=update.dnsexit.com ## defaults to update.dnsexit.com + script=/RemoteUpdate.sv ## defaults to /RemoteUpdate.sv + login=service-userid ## userid registered with the service + password=service-password ## password registered with the service + fully.qualified.host ## the host registered with the service. + +Example ${program}.conf file entries: + ## single host update + protocol=dnsexit \\ + login=service-userid \\ + password=service-password \\ + fully.qualified.host + +EoEXAMPLE +} +###################################################################### +## nic_dnsexit_update +## +## written by Gonzalo Pérez de Olaguer Córdoba +## +## based on https://www.dnsexit.com/Direct.sv?cmd=ipClients +## fetches this URL to update: +## https://update.dnsexit.com/RemoteUpdate.sv?login=yourlogin&password=yourpassword& +## host=yourhost.yourdomain.com&myip=xxx.xx.xx.xxx +## +###################################################################### +sub nic_dnsexit_update { + debug("\nnic_dnsexit_update -------------------"); + + my %status = ( + '0' => [ 'good', 'Success' ], + '1' => [ 'nochg', 'IP is the same as the IP on the system' ], + '2' => [ 'badauth', 'Invalid password' ], + '3' => [ 'badauth', 'User not found' ], + '4' => [ 'nochg', 'IP not changed. To save our system resources, please don\'t post updates unless the IP got changed.' ], + '10' => [ 'error', 'Hostname is not specified' ], + '11' => [ 'nohost', 'fail to find the domain' ], + '13' => [ 'error', 'parameter validation error' ], + ); + + ## update each configured host + foreach my $h (@_) { + my $ip = delete $config{$h}{'wantip'}; + info("setting IP address to %s for %s", $ip, $h); + verbose("UPDATE:","updating %s", $h); + + # Set the URL that we're going to update + my $url; + $url = "https://$config{$h}{'server'}$config{$h}{'script'}"; + $url .= "?login=$config{$h}{'login'}"; + $url .= "&password=$config{$h}{'password'}"; + $url .= "&host=$h"; + $url .= "&myip="; + $url .= $ip if $ip; + + # Try to get URL + my $reply = geturl( + proxy => opt('proxy'), + url => $url + ); + + # No response, declare as failed + if (!defined($reply) || !$reply) { + failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'}); + last; + } + last if !header_ok($h, $reply); + + # Response found + if ($reply =~ /(\d+)=(.+)/) { + my ($statuscode, $statusmsg) = ($1, $2); + if (exists $status{$statuscode}) { + my ($status, $message) = @{ $status{$statuscode} }; + if ($status =~ m'^(good|nochg)$') { + $config{$h}{'ip'} = $ip; + $config{$h}{'mtime'} = $now; + } + $config{$h}{'status'} = $status; + if ($status eq 'good') { + success("updating %s: good: IP address set to %s", $h, $ip); + } else { + warning("updating %s: %s: %s", $h, $status, $message); + } + } else { + $config{$h}{'status'} = 'failed'; + failed("updating %s: failed: unrecognized status code (%s)", $h, $statuscode); + } + } else { + $config{$h}{'status'} = 'failed'; + warning("SENT: %s", $url) unless opt('verbose'); + warning("REPLIED: %s", $reply); + failed("updating %s: unrecognized reply.", $h); + } + } +} ###################################################################### ## nic_noip_update ## Note: uses same features as nic_dyndns2_update, less return codes