Merge branch 'master' into cdmon
This commit is contained in:
commit
680573372d
13 changed files with 691 additions and 462 deletions
25
ChangeLog.md
25
ChangeLog.md
|
|
@ -3,7 +3,31 @@
|
|||
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
|
||||
|
||||
### Breaking changes
|
||||
|
||||
* 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.
|
||||
|
||||
### New features
|
||||
|
||||
* Added support for domaindiscount24.com
|
||||
* Added support for domeneshop.no
|
||||
* Added support for Enom
|
||||
* Added support for Mythic Beasts Dynamic DNS
|
||||
* Added support for njal.la
|
||||
* Added support for Porkbun
|
||||
* Added support for IPv6 to the EasyDNS and DuckDNS provider
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* DynDNS2 now uses the newer ipv4/ipv6 syntax's
|
||||
* The OVH provider now ignores extra data returned
|
||||
|
||||
## 2022-10-20 v3.10.0
|
||||
|
||||
### New features
|
||||
|
||||
* Added support for domaindiscount24.com
|
||||
|
|
@ -12,6 +36,7 @@ repository history](https://github.com/ddclient/ddclient/commits/master).
|
|||
## 2022-05-15 v3.10.0_2
|
||||
|
||||
### Bug fixes
|
||||
|
||||
* Fix version number being unable to parse
|
||||
|
||||
## 2022-05-15 v3.10.0_1
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ EXTRA_DIST = \
|
|||
sample-etc_dhclient-exit-hooks \
|
||||
sample-etc_dhcpc_dhcpcd-eth0.exe \
|
||||
sample-etc_ppp_ip-up.local \
|
||||
sample-etc_rc.d_ddclient.freebsd \
|
||||
sample-etc_rc.d_init.d_ddclient \
|
||||
sample-etc_rc.d_init.d_ddclient.alpine \
|
||||
sample-etc_rc.d_init.d_ddclient.lsb \
|
||||
sample-etc_rc.d_init.d_ddclient.redhat \
|
||||
sample-etc_rc.d_init.d_ddclient.ubuntu \
|
||||
sample-etc_systemd.service \
|
||||
sample-get-ip-from-fritzbox
|
||||
CLEANFILES =
|
||||
|
|
|
|||
82
README.md
82
README.md
|
|
@ -29,6 +29,7 @@ Dynamic DNS services currently supported include:
|
|||
DonDominio - See https://www.dondominio.com for details
|
||||
NearlyFreeSpeech.net - See https://www.nearlyfreespeech.net/services/dns for details
|
||||
OVH - See https://www.ovh.com for details
|
||||
Porkbun - See https://porkbun.com/
|
||||
ClouDNS - See https://www.cloudns.net
|
||||
dinahosting - See https://dinahosting.com
|
||||
Gandi - See https://gandi.net
|
||||
|
|
@ -36,6 +37,9 @@ Dynamic DNS services currently supported include:
|
|||
1984.is - See https://www.1984.is/product/freedns/ for details
|
||||
Njal.la - See https://njal.la/docs/ddns/
|
||||
regfish.de - See https://www.regfish.de/domains/dyndns/ for details
|
||||
domenehsop - See https://api.domeneshop.no/docs/#tag/ddns/paths/~1dyndns~1update/get
|
||||
Mythic Beasts - See https://www.mythic-beasts.com/support/api/dnsv2/dynamic-dns for details
|
||||
Enom - See https://www.enom.com for details
|
||||
cdmon.org - See https://ticket.cdmon.com/ca/support/solutions/articles/7000005922-api-d-actualitzaci%C3%B3-de-ip-del-dns-gratis-din%C3%A0mic
|
||||
|
||||
`ddclient` now supports many cable and DSL broadband routers.
|
||||
|
|
@ -113,82 +117,6 @@ start the first time by hand
|
|||
|
||||
systemctl start ddclient.service
|
||||
|
||||
#### Redhat style rc files and daemon-mode
|
||||
|
||||
cp sample-etc_rc.d_init.d_ddclient /etc/rc.d/init.d/ddclient
|
||||
|
||||
enable automatic startup when booting. also check your distribution
|
||||
|
||||
/sbin/chkconfig --add ddclient
|
||||
|
||||
start the first time by hand
|
||||
|
||||
/etc/rc.d/init.d/ddclient start
|
||||
|
||||
#### Alpine style rc files and daemon-mode
|
||||
|
||||
cp sample-etc_rc.d_init.d_ddclient.alpine /etc/init.d/ddclient
|
||||
|
||||
enable automatic startup when booting
|
||||
|
||||
rc-update add ddclient
|
||||
|
||||
make sure you have perl installed
|
||||
|
||||
apk add perl
|
||||
|
||||
start the first time by hand
|
||||
|
||||
rc-service ddclient start
|
||||
|
||||
#### Ubuntu style rc files and daemon-mode
|
||||
|
||||
cp sample-etc_rc.d_init.d_ddclient.ubuntu /etc/init.d/ddclient
|
||||
|
||||
enable automatic startup when booting
|
||||
|
||||
update-rc.d ddclient defaults
|
||||
|
||||
make sure you have perl and the required modules installed
|
||||
|
||||
apt-get install perl libdata-validate-ip-perl libio-socket-ssl-perl
|
||||
|
||||
if you plan to use cloudflare or feedns you need the perl json module
|
||||
|
||||
apt-get install libjson-pp-perl
|
||||
|
||||
for IPv6 you also need to instal the perl io-socket-inet6 module
|
||||
|
||||
apt install libio-socket-inet6-perl
|
||||
|
||||
start the first time by hand
|
||||
|
||||
service ddclient start
|
||||
|
||||
#### FreeBSD style rc files and daemon mode
|
||||
|
||||
mkdir -p /usr/local/etc/rc.d
|
||||
cp sample-etc_rc.d_ddclient.freebsd /usr/local/etc/rc.d/ddclient
|
||||
|
||||
enable automatic startup when booting
|
||||
|
||||
sysrc ddclient_enable=YES
|
||||
|
||||
make sure you have perl and the required modules installed
|
||||
|
||||
pkg install perl5 p5-Data-Validate-IP p5-IO-Socket-SSL
|
||||
|
||||
if you plan to use cloudflare or feedns you need the perl json module
|
||||
|
||||
pkg install p5-JSON-PP
|
||||
|
||||
start the service manually for the first time
|
||||
|
||||
service ddclient start
|
||||
|
||||
|
||||
If you are not using daemon-mode, configure cron and dhcp or ppp as described below.
|
||||
|
||||
## TROUBLESHOOTING
|
||||
|
||||
1. enable debugging and verbose messages: ``$ ddclient -daemon=0 -debug -verbose -noquiet``
|
||||
|
|
@ -248,7 +176,7 @@ not become stale.
|
|||
cp sample-etc_cron.d_ddclient /etc/cron.d/ddclient
|
||||
vi /etc/cron.d/ddclient
|
||||
|
||||
## USING DDCLIENT WITH `dhcpcd-1.3.17`
|
||||
## USING DDCLIENT WITH `dhcpcd`
|
||||
|
||||
If you are using dhcpcd-1.3.17 or thereabouts, you can easily update
|
||||
your DynDNS entry automatically every time your lease is obtained
|
||||
|
|
|
|||
13
README.ssl
13
README.ssl
|
|
@ -1,13 +0,0 @@
|
|||
Since 3.7.0, ddclient support ssl-updates
|
||||
To use ssl, put "ssl=yes" in your configuration and make sure
|
||||
you have IO::Socket::SSL.
|
||||
|
||||
On debian, you need libio-socket-ssl-perl to have IO::Socket::SSL
|
||||
|
||||
On alpine, you need perl-io-socket-ssl to have IO::Socket::SSL
|
||||
|
||||
ssl support is tested on folowing dynamic dns providers:
|
||||
- dyndns.com
|
||||
- freemyip.com
|
||||
- DNS Made Easy
|
||||
- dondominio.com
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
AC_PREREQ([2.63])
|
||||
AC_INIT([ddclient], [3.10.1])
|
||||
AC_INIT([ddclient], [3.11.0])
|
||||
AC_CONFIG_SRCDIR([ddclient.in])
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
|
|
|||
|
|
@ -285,6 +285,15 @@ ssl=yes # use ssl-support. Works with
|
|||
# password=your_password
|
||||
# test.example.com
|
||||
|
||||
##
|
||||
## Porkbun (https://porkbun.com/)
|
||||
##
|
||||
# protocol=porkbun
|
||||
# apikey=APIKey
|
||||
# secretapikey=SecretAPIKey
|
||||
# host.example.com,host2.sub.example.com
|
||||
# on-root-domain=yes example.com,sub.example.com
|
||||
|
||||
##
|
||||
## ClouDNS (https://www.cloudns.net)
|
||||
##
|
||||
|
|
@ -308,6 +317,14 @@ ssl=yes # use ssl-support. Works with
|
|||
#password=mypassword, \
|
||||
#subdomain-1.domain.com,subdomain-2.domain.com
|
||||
|
||||
##
|
||||
## domeneshop (www.domeneshop.no)
|
||||
##
|
||||
# protocol=domeneshop
|
||||
# login=<token>
|
||||
# password=<secret>
|
||||
# subdomain-1.domain.com,subdomain-2.domain.com
|
||||
|
||||
##
|
||||
## Njal.la (http://njal.la/)
|
||||
##
|
||||
|
|
@ -323,6 +340,15 @@ ssl=yes # use ssl-support. Works with
|
|||
# password=mypassword
|
||||
# my-domain.com
|
||||
|
||||
##
|
||||
## Enom (www.enom.com)
|
||||
##
|
||||
# protocol=enom,
|
||||
# login=domain.name,
|
||||
# password=domain-password
|
||||
# my-domain.com
|
||||
|
||||
|
||||
##
|
||||
## cdmon.org (https://dinamico.cdmon.org/)
|
||||
##
|
||||
|
|
|
|||
668
ddclient.in
668
ddclient.in
|
|
@ -490,17 +490,32 @@ my %variables = (
|
|||
'host' => setv(T_STRING,1, 1, '', undef),
|
||||
|
||||
'use' => setv(T_USE, 0, 0, 'ip', undef),
|
||||
'usev4' => setv(T_USEV4, 0, 0, 'disabled', undef),
|
||||
'usev6' => setv(T_USEV6, 0, 0, 'disabled', undef),
|
||||
'if' => setv(T_IF, 0, 0, 'ppp0', undef),
|
||||
'ifv4' => setv(T_IF, 0, 0, 'default', undef),
|
||||
'ifv6' => setv(T_IF, 0, 0, 'default', undef),
|
||||
'web' => setv(T_STRING,0, 0, 'dyndns', undef),
|
||||
'web-skip' => setv(T_STRING,0, 0, '', undef),
|
||||
'web-ssl-validate' => setv(T_BOOL, 0, 0, 1, undef),
|
||||
'webv4' => setv(T_STRING,0, 0, 'googledomains', undef),
|
||||
'webv4-skip' => setv(T_STRING,1, 0, '', undef),
|
||||
'webv6' => setv(T_STRING,0, 0, 'googledomains', undef),
|
||||
'webv6-skip' => setv(T_STRING,1, 0, '', undef),
|
||||
'fw' => setv(T_ANY, 0, 0, '', undef),
|
||||
'fw-skip' => setv(T_STRING,0, 0, '', undef),
|
||||
'fw-login' => setv(T_LOGIN, 0, 0, '', undef),
|
||||
'fw-password' => setv(T_PASSWD,0, 0, '', undef),
|
||||
'fw-ssl-validate' => setv(T_BOOL, 0, 0, 1, undef),
|
||||
'fwv4' => setv(T_ANY, 0, 0, '', undef),
|
||||
'fwv4-skip' => setv(T_STRING,1, 0, '', undef),
|
||||
'fwv6' => setv(T_ANY, 0, 0, '', undef),
|
||||
'fwv6-skip' => setv(T_STRING,1, 0, '', undef),
|
||||
'cmd' => setv(T_PROG, 0, 0, '', undef),
|
||||
'cmd-skip' => setv(T_STRING,0, 0, '', undef),
|
||||
'cmdv4' => setv(T_PROG, 0, 0, '', undef),
|
||||
'cmdv6' => setv(T_PROG, 0, 0, '', undef),
|
||||
|
||||
'ip' => setv(T_IP, 0, 1, undef, undef), #TODO remove from cache?
|
||||
'ipv4' => setv(T_IPV4, 0, 1, undef, undef),
|
||||
'ipv6' => setv(T_IPV6, 0, 1, undef, undef),
|
||||
|
|
@ -639,6 +654,15 @@ my %services = (
|
|||
'host' => setv(T_NUMBER, 1, 1, 0, undef),
|
||||
},
|
||||
},
|
||||
'domeneshop' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_domeneshop_update,
|
||||
'examples' => \&nic_domeneshop_examples,
|
||||
'variables' => {
|
||||
%{$variables{'service-common-defaults'}},
|
||||
'server' => setv(T_FQDNP, 1, 0, 'api.domeneshop.no', undef),
|
||||
},
|
||||
},
|
||||
'duckdns' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_duckdns_update,
|
||||
|
|
@ -753,6 +777,16 @@ my %services = (
|
|||
'zone' => setv(T_FQDN, 1, 0, '', undef),
|
||||
},
|
||||
},
|
||||
'mythicdyn' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_mythicdyn_update,
|
||||
'examples' => \&nic_mythicdyn_examples,
|
||||
'variables' => {
|
||||
%{$variables{'service-common-defaults'}},
|
||||
'min-interval' => setv(T_DELAY, 0, 0, interval('5m'), 0),
|
||||
'server' => setv(T_FQDNP, 1, 0, 'api.mythic-beasts.com', undef),
|
||||
},
|
||||
},
|
||||
'namecheap' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_namecheap_update,
|
||||
|
|
@ -833,6 +867,21 @@ my %services = (
|
|||
'server' => setv(T_FQDNP, 1, 0, 'www.ovh.com', undef),
|
||||
},
|
||||
},
|
||||
'porkbun' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_porkbun_update,
|
||||
'examples' => \&nic_porkbun_examples,
|
||||
'variables' => {
|
||||
'apikey' => setv(T_PASSWD, 1, 0, '', undef),
|
||||
'secretapikey' => setv(T_PASSWD, 1, 0, '', undef),
|
||||
'on-root-domain' => setv(T_BOOL, 0, 0, 0, undef),
|
||||
'login' => setv(T_LOGIN, 0, 0, 'unused', undef),
|
||||
'password' => setv(T_PASSWD, 0, 0, 'unused', undef),
|
||||
'use' => setv(T_USE, 0, 0, 'disabled', undef),
|
||||
'usev4' => setv(T_USEV4, 0, 0, 'disabled', undef),
|
||||
'usev6' => setv(T_USEV6, 0, 0, 'disabled', undef),
|
||||
},
|
||||
},
|
||||
'sitelutions' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_sitelutions_update,
|
||||
|
|
@ -917,6 +966,16 @@ my %services = (
|
|||
$variables{'service-common-defaults'},
|
||||
),
|
||||
},
|
||||
'enom' => {
|
||||
'updateable' => undef,
|
||||
'update' => \&nic_enom_update,
|
||||
'examples' => \&nic_enom_examples,
|
||||
'variables' => {
|
||||
%{$variables{'service-common-defaults'}},
|
||||
'server' => setv(T_FQDNP, 1, 0, 'dynamic.name-services.com', undef),
|
||||
'min-interval' => setv(T_DELAY, 0, 0, 0, interval('5m')),
|
||||
},
|
||||
},
|
||||
);
|
||||
$variables{'merged'} = {
|
||||
map({ %{$services{$_}{'variables'}} } keys(%services)),
|
||||
|
|
@ -1181,6 +1240,7 @@ sub update_nics {
|
|||
my $usev6 = opt('usev6', $h) // 'disabled';
|
||||
$use = 'disabled' if ($use eq 'no'); # backward compatibility
|
||||
$usev6 = 'disabled' if ($usev6 eq 'no'); # backward compatibility
|
||||
$use = 'disabled' if ($usev4 ne 'disabled') || ($usev6 ne 'disabled');
|
||||
my $arg_ip = opt('ip', $h) // '';
|
||||
my $arg_ipv4 = opt('ipv4', $h) // '';
|
||||
my $arg_ipv6 = opt('ipv6', $h) // '';
|
||||
|
|
@ -1739,7 +1799,7 @@ sub init_config {
|
|||
$proto = opt('protocol') if !defined($proto);
|
||||
|
||||
load_sha1_support($proto) if (grep (/^$proto$/, ("freedns", "nfsn")));
|
||||
load_json_support($proto) if (grep (/^$proto$/, ("1984", "cloudflare", "gandi", "godaddy", "hetzner", "yandex", "nfsn", "njalla")));
|
||||
load_json_support($proto) if (grep (/^$proto$/, ("1984", "cloudflare", "gandi", "godaddy", "hetzner", "yandex", "nfsn", "njalla", "porkbun")));
|
||||
|
||||
if (!exists($services{$proto})) {
|
||||
warning("skipping host: %s: unrecognized protocol '%s'", $h, $proto);
|
||||
|
|
@ -3610,6 +3670,7 @@ sub nic_updateable {
|
|||
my $usev6 = opt('usev6', $host) // 'disabled';
|
||||
$use = 'disabled' if ($use eq 'no'); # backward compatibility
|
||||
$usev6 = 'disabled' if ($usev6 eq 'no'); # backward compatibility
|
||||
$use = 'disabled' if ($usev4 ne 'disabled') || ($usev6 ne 'disabled');
|
||||
|
||||
# If we have a valid IP address and we have previously warned that it was invalid.
|
||||
# reset the warning count back to zero.
|
||||
|
|
@ -3810,7 +3871,7 @@ sub nic_updateable {
|
|||
success("%s: skipped: IP address was already set to %s.", $host, $ip);
|
||||
}
|
||||
if ($usev4 ne 'disabled') {
|
||||
success("%s: skipped: IPv4 address was already set to %s.", $host, $ipv6);
|
||||
success("%s: skipped: IPv4 address was already set to %s.", $host, $ipv4);
|
||||
}
|
||||
if ($usev6 ne 'disabled') {
|
||||
success("%s: skipped: IPv6 address was already set to %s.", $host, $ipv6);
|
||||
|
|
@ -3852,7 +3913,9 @@ sub header_ok {
|
|||
$ok = 1;
|
||||
|
||||
} elsif ($result eq '401') {
|
||||
failed("updating %s: authorization failed (%s)", $host, $line);
|
||||
failed("updating %s: authentication failed (%s)", $host, $line);
|
||||
} elsif ($result eq '403') {
|
||||
failed("updating %s: not authorized (%s)", $host, $line);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
|
@ -4057,10 +4120,13 @@ sub nic_dyndns2_update {
|
|||
my @hosts = @{$groups{$sig}};
|
||||
my $hosts = join(',', @hosts);
|
||||
my $h = $hosts[0];
|
||||
my $ip = $config{$h}{'wantip'};
|
||||
delete $config{$_}{'wantip'} foreach @hosts;
|
||||
my $ipv4 = $config{$h}{'wantipv4'};
|
||||
my $ipv6 = $config{$h}{'wantipv6'};
|
||||
delete $config{$_}{'wantipv4'} foreach @hosts;
|
||||
delete $config{$_}{'wantipv6'} foreach @hosts;
|
||||
|
||||
info("setting IP address to %s for %s", $ip, $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);
|
||||
|
||||
## Select the DynDNS system to update
|
||||
|
|
@ -4079,7 +4145,11 @@ sub nic_dyndns2_update {
|
|||
|
||||
$url .= "&hostname=$hosts";
|
||||
$url .= "&myip=";
|
||||
$url .= $ip if $ip;
|
||||
$url .= $ipv4 if $ipv4;
|
||||
if ($ipv6) {
|
||||
$url .= "," if $ipv4;
|
||||
$url .= $ipv6;
|
||||
}
|
||||
|
||||
## some args are not valid for a custom domain.
|
||||
$url .= "&wildcard=ON" if ynu($config{$h}{'wildcard'}, 1, 0, 0);
|
||||
|
|
@ -4102,7 +4172,6 @@ sub nic_dyndns2_update {
|
|||
|
||||
my @reply = split /\n/, $reply;
|
||||
my $state = 'header';
|
||||
my $returnedip = $ip;
|
||||
|
||||
foreach my $line (@reply) {
|
||||
if ($state eq 'header') {
|
||||
|
|
@ -4116,22 +4185,28 @@ sub nic_dyndns2_update {
|
|||
|
||||
# bug #10: some dyndns providers does not return the IP so
|
||||
# we can't use the returned IP
|
||||
my ($status, $returnedip) = split / /, lc $line;
|
||||
$ip = $returnedip if (not $ip);
|
||||
my ($status, $returnedips) = split / /, lc $line;
|
||||
my $h = shift @hosts;
|
||||
|
||||
$config{$h}{'status'} = $status;
|
||||
$config{$h}{'status-ipv4'} = $status if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = $status if $ipv6;
|
||||
if ($status eq 'good') {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
success("updating %s: %s: IP address set to %s", $h, $status, $ip);
|
||||
success("updating %s: %s: IPv4 address set to %s", $h, $status, $ipv4) if $ipv4;
|
||||
success("updating %s: %s: IPv6 address set to %s", $h, $status, $ipv6) if $ipv6;
|
||||
|
||||
} elsif (exists $errors{$status}) {
|
||||
if ($status eq 'nochg') {
|
||||
warning("updating %s: %s: %s", $h, $status, $errors{$status});
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'ipv4'} = $ipv4 if $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6 if $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$config{$h}{'status-ipv4'} = 'good' if $ipv4;
|
||||
$config{$h}{'status-ipv6'} = 'good' if $ipv6;
|
||||
|
||||
} else {
|
||||
failed("updating %s: %s: %s", $h, $status, $errors{$status});
|
||||
|
|
@ -4476,6 +4551,86 @@ sub nic_dslreports1_update {
|
|||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_domeneshop_examples
|
||||
######################################################################
|
||||
sub nic_domeneshop_examples {
|
||||
return <<"EoEXAMPLE";
|
||||
o 'domeneshop'
|
||||
|
||||
API is documented here: https://api.domeneshop.no/docs/
|
||||
|
||||
To generate credentials, visit https://www.domeneshop.no/admin?view=api after logging in to the control panel at
|
||||
https://www.domeneshop.no/admin?view=api
|
||||
|
||||
Configuration variables applicable to the 'domeneshop' api are:
|
||||
protocol=domeneshop ##
|
||||
login=token ## api-token
|
||||
password=secret ## api-secret
|
||||
domain.example.com ## the host registered with the service. ## the host registered with the service.
|
||||
|
||||
Example ${program}.conf file entries:
|
||||
## single host update
|
||||
protocol=domeneshop
|
||||
login=username
|
||||
password=your-password
|
||||
my.example.com
|
||||
|
||||
EoEXAMPLE
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_domeneshop_update
|
||||
######################################################################
|
||||
sub nic_domeneshop_update {
|
||||
debug("\nnic_domeneshop_update -------------------");
|
||||
|
||||
my $endpointPath = "/v0/dyndns/update";
|
||||
|
||||
## update each configured host
|
||||
## should improve to update in one pass
|
||||
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 to update
|
||||
my $url;
|
||||
$url = $globals{'ssl'} ? "https://" : "http://";
|
||||
$url .= "$config{$h}{'server'}$endpointPath?hostname=$h&myip=$ip";
|
||||
|
||||
# Try to get URL
|
||||
my $reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url,
|
||||
login => $config{$h}{'login'},
|
||||
password => $config{$h}{'password'},
|
||||
);
|
||||
|
||||
# No response, declare as failed
|
||||
if (!defined($reply) || !$reply) {
|
||||
failed("Updating %s: Could not connect to %s.", $h, $config{$h}{'server'});
|
||||
next;
|
||||
}
|
||||
next if !header_ok($h, $reply);
|
||||
|
||||
# evaluate response
|
||||
my @reply = split /\n/, $reply;
|
||||
my $status = shift(@reply);
|
||||
my $message = pop(@reply);
|
||||
if ($status =~ /204/) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
success("updating %s: good: IP address set to %s", $h, $ip);
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
failed("updating %s: Server said: '%s' '%s'", $h, $status, $message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
######################################################################
|
||||
## nic_zoneedit1_examples
|
||||
######################################################################
|
||||
|
|
@ -4680,10 +4835,12 @@ sub nic_easydns_update {
|
|||
my @hosts = @{$groups{$sig}};
|
||||
my $hosts = join(',', @hosts);
|
||||
my $h = $hosts[0];
|
||||
my $ip = $config{$h}{'wantip'};
|
||||
delete $config{$_}{'wantip'} foreach @hosts;
|
||||
my $ipv4 = $config{$h}{'wantipv4'};
|
||||
my $ipv6 = $config{$h}{'wantipv6'};
|
||||
delete $config{$_}{'wantipv4'} foreach @hosts;
|
||||
delete $config{$_}{'wantipv6'} foreach @hosts;
|
||||
|
||||
info("setting IP address to %s for %s", $ip, $hosts);
|
||||
info("setting IP address to %s %s for %s", $ipv4, $ipv6, $hosts);
|
||||
verbose("UPDATE:", "updating %s", $hosts);
|
||||
|
||||
#'https://api.cp.easydns.com/dyn/generic.php?hostname=test.burry.ca&myip=10.20.30.40&wildcard=ON'
|
||||
|
|
@ -4692,7 +4849,11 @@ sub nic_easydns_update {
|
|||
$url = "https://$config{$h}{'server'}$config{$h}{'script'}?";
|
||||
$url .= "hostname=$hosts";
|
||||
$url .= "&myip=";
|
||||
$url .= $ip if $ip;
|
||||
$url .= $ipv4 if $ipv4;
|
||||
foreach my $ipv6a ($ipv6) {
|
||||
$url .= "&myip=";
|
||||
$url .= $ipv6a
|
||||
}
|
||||
$url .= "&wildcard=" . ynu($config{$h}{'wildcard'}, 'ON', 'OFF', 'OFF') if defined $config{$h}{'wildcard'};
|
||||
|
||||
if ($config{$h}{'mx'}) {
|
||||
|
|
@ -4729,9 +4890,10 @@ sub nic_easydns_update {
|
|||
|
||||
$config{$h}{'status'} = $status;
|
||||
if ($status eq 'NOERROR') {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'ipv4'} = $ipv4;
|
||||
$config{$h}{'ipv6'} = $ipv6;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
success("updating %s: %s: IP address set to %s", $h, $status, $ip);
|
||||
success("updating %s: %s: IP address set to %s %s", $h, $status, $ipv4, $ipv6);
|
||||
|
||||
} elsif ($status =~ /TOOSOON/) {
|
||||
## make sure we wait at least a little
|
||||
|
|
@ -5910,6 +6072,82 @@ sub nic_googledomains_update {
|
|||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_mythicdyn_examples
|
||||
##
|
||||
## written by Reuben Thomas
|
||||
##
|
||||
######################################################################
|
||||
sub nic_mythicdyn_examples {
|
||||
return <<"EoEXAMPLE";
|
||||
o 'mythicdyn'
|
||||
|
||||
The 'mythicdyn' protocol is used by the Dynamic DNS service offered by
|
||||
www.mythic-beasts.com.
|
||||
|
||||
Configuration variables applicable to the 'mythicdyn' protocol are:
|
||||
protocol=mythicdyn ##
|
||||
ipv6=no|yes ## whether to set an A record (default, ipv6=no)
|
||||
## or AAAA record (ipv6=yes).
|
||||
login=service-login ## the user name provided by the admin interface
|
||||
password=service-password ## the password provided by the admin interface
|
||||
fully.qualified.host ## the host registered with the service
|
||||
|
||||
Note: this service automatically sets the IP address to that from which the
|
||||
request comes, so the IP address detected by ddclient is only used to keep
|
||||
track of when it needs updating.
|
||||
|
||||
Example ${program}.conf file entries:
|
||||
## Single host update.
|
||||
protocol=mythicdyn, \\
|
||||
login=service-login \\
|
||||
password=service-password, \\
|
||||
host.example.com
|
||||
|
||||
## Multiple host update.
|
||||
protocol=mythicdyn, \\
|
||||
login=service-login \\
|
||||
password=service-password, \\
|
||||
hosta.example.com,hostb.sub.example.com
|
||||
EoEXAMPLE
|
||||
}
|
||||
######################################################################
|
||||
## nic_mythicdyn_update
|
||||
######################################################################
|
||||
sub nic_mythicdyn_update {
|
||||
debug("\nnic_mythicdyn_update --------------------");
|
||||
|
||||
# Update each set configured host.
|
||||
foreach my $h (@_) {
|
||||
info("%s -- Setting IP address.", $h);
|
||||
|
||||
my $ipversion = $config{$h}{'ipv6'} ? '6' : '4';
|
||||
|
||||
my $reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => "https://ipv$ipversion.$config{$h}{'server'}/dns/v2/dynamic/$h",
|
||||
method => 'POST',
|
||||
login => $config{$h}{'login'},
|
||||
password => $config{$h}{'password'},
|
||||
ipversion => $ipversion,
|
||||
);
|
||||
unless ($reply) {
|
||||
failed("Updating service %s failed: %s", $h, $config{$h}{'server'});
|
||||
next;
|
||||
}
|
||||
|
||||
my $ok = header_ok($h, $reply);
|
||||
if ($ok) {
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = "good";
|
||||
|
||||
success("%s -- Updated successfully.", $h);
|
||||
} else {
|
||||
failed("%s -- Failed to update.", $h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_nsupdate_examples
|
||||
######################################################################
|
||||
|
|
@ -6282,7 +6520,7 @@ sub nic_hetzner_update {
|
|||
$config{$domain}{"status-ipv$ipv"} = 'failed';
|
||||
|
||||
# Get DNS 'A' or 'AAAA' record ID
|
||||
$url = "https://$config{$key}{'server'}/records";
|
||||
$url = "https://$config{$key}{'server'}/records?zone_id=$zone_id";
|
||||
$reply = geturl(proxy => opt('proxy'),
|
||||
url => $url,
|
||||
headers => $headers
|
||||
|
|
@ -6299,7 +6537,7 @@ sub nic_hetzner_update {
|
|||
next;
|
||||
}
|
||||
# Pull the ID out of the json, messy
|
||||
my ($dns_rec_id) = map { ($_->{name} eq $hostname && $_->{type} eq $type && &zone_id eq $_{zone_id}) ? $_->{id} : ()} @{$response->{records}};
|
||||
my ($dns_rec_id) = map { ($_->{name} eq $hostname && $_->{type} eq $type) ? $_->{id} : ()} @{$response->{records}};
|
||||
|
||||
# Set domain
|
||||
my $http_method="";
|
||||
|
|
@ -6511,7 +6749,11 @@ sub nic_duckdns_update {
|
|||
$url .= $h;
|
||||
$url .= "&token=";
|
||||
$url .= $config{$h}{'password'};
|
||||
$url .= "&ip=";
|
||||
if (is_ipv6($ip)) {
|
||||
$url .= "&ipv6=";
|
||||
} else {
|
||||
$url .= "&ip=";
|
||||
}
|
||||
$url .= $ip;
|
||||
|
||||
|
||||
|
|
@ -6526,15 +6768,26 @@ sub nic_duckdns_update {
|
|||
next if !header_ok($h, $reply);
|
||||
|
||||
my @reply = split /\n/, $reply;
|
||||
my $returned = pop(@reply);
|
||||
if ($returned =~ /OK/) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
success("updating %s: good: IP address set to %s", $h, $ip);
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
failed("updating %s: Server said: '%s'", $h, $returned);
|
||||
my $state = 'noresult';
|
||||
my $line = '';
|
||||
|
||||
foreach $line (@reply) {
|
||||
if ($line eq 'OK') {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
$state = 'result';
|
||||
success("updating %s: good: IP address set to %s", $h, $ip);
|
||||
|
||||
} elsif ($line eq 'KO') {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
$state = 'result';
|
||||
failed("updating %s: Server said: '%s'", $h, $line);
|
||||
}
|
||||
}
|
||||
|
||||
if ($state eq 'noresult') {
|
||||
failed("updating %s: Server said: '%s'", $h, $line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7005,8 +7258,8 @@ sub nic_ovh_update {
|
|||
}
|
||||
|
||||
my @reply = split /\n/, $reply;
|
||||
my $returned = pop(@reply);
|
||||
if ($returned =~ /good/ || $returned =~ /nochg/) {
|
||||
my $returned = List::Util::first { $_ =~ /good/ || $_ =~ /nochg/ } @reply;
|
||||
if ($returned) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
|
|
@ -7017,7 +7270,270 @@ sub nic_ovh_update {
|
|||
}
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
failed("updating %s: Server said: '%s'", $h, $returned);
|
||||
failed("updating %s: Server said: '%s'", $h, $reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_porkbun_examples
|
||||
######################################################################
|
||||
sub nic_porkbun_examples {
|
||||
return <<"EoEXAMPLE";
|
||||
o 'porkbun'
|
||||
|
||||
The 'porkbun' protocol is used for porkbun (https://porkbun.com/).
|
||||
The API is documented here: https://porkbun.com/api/json/v3/documentation
|
||||
|
||||
Before setting up, it is necessary to create your API Key by referring to the following page.
|
||||
|
||||
https://kb.porkbun.com/article/190-getting-started-with-the-porkbun-api
|
||||
|
||||
Available configuration variables:
|
||||
* apikey (required): API Key of Porkbun API
|
||||
* secretapikey (required): Secret API Key of Porkbun API
|
||||
* on-root-domain=yes or no (default: no): Indicates whether the specified domain name (FQDN) is
|
||||
an unnamed record (Zone APEX) in a zone.
|
||||
It is useful to specify it as a local variable as shown in the example.
|
||||
* usev4, usev6 : These configuration variables can be specified as local variables to override
|
||||
the global settings. It is useful to finely control IPv4 or IPv6 as shown in the example.
|
||||
* use (deprecated) : This parameter is deprecated but can be overridden like the above parameters.
|
||||
|
||||
Limitations:
|
||||
* Multiple same name records (for round robin) are not supported.
|
||||
The same IP address is set for all, creating meaningless extra records.
|
||||
|
||||
Example ${program}.conf file entry:
|
||||
protocol=porkbun
|
||||
apikey=APIKey
|
||||
secretapikey=SecretAPIKey
|
||||
host.example.com,host2.sub.example.com
|
||||
on-root-domain=yes example.com,sub.example.com
|
||||
|
||||
Additional example to finely control IPv4 or IPv6 :
|
||||
# Example 01 : Global enable both IPv4 and IPv6, and update both records.
|
||||
usev4=webv4
|
||||
usev6=ifv6, ifv6=enp1s0
|
||||
|
||||
protocol=porkbun
|
||||
apikey=APIKey
|
||||
secretapikey=SecretAPIKey
|
||||
host.example.com,host2.sub.example.com
|
||||
|
||||
# Example 02 : Global enable only IPv4, and update only IPv6 record.
|
||||
usev4=webv4
|
||||
|
||||
protocol=porkbun
|
||||
apikey=APIKey
|
||||
secretapikey=SecretAPIKey
|
||||
usev6=ifv6, ifv6=enp1s0, usev4=disabled ipv6.example.com
|
||||
|
||||
EoEXAMPLE
|
||||
}
|
||||
|
||||
######################################################################
|
||||
## nic_porkbun_update
|
||||
######################################################################
|
||||
sub nic_porkbun_update {
|
||||
debug("\nnic_porkbun_update -------------------");
|
||||
|
||||
## update each configured host
|
||||
## should improve to update in one pass
|
||||
foreach my $host (@_) {
|
||||
my ($sub_domain, $domain);
|
||||
if ($config{$host}{'on-root-domain'}) {
|
||||
$sub_domain = '';
|
||||
$domain = $host;
|
||||
} else {
|
||||
($sub_domain, $domain) = split(/\./, $host, 2);
|
||||
}
|
||||
my $ipv4 = delete $config{$host}{'wantipv4'};
|
||||
my $ipv6 = delete $config{$host}{'wantipv6'};
|
||||
if (is_ipv4($ipv4)) {
|
||||
info("setting IPv4 address to %s for %s", $ipv4, $host);
|
||||
verbose("UPDATE:","updating %s", $host);
|
||||
|
||||
my $url = "https://porkbun.com/api/json/v3/dns/retrieveByNameType/$domain/A/$sub_domain";
|
||||
my $data = encode_json({
|
||||
secretapikey => $config{$host}{'secretapikey'},
|
||||
apikey => $config{$host}{'apikey'},
|
||||
});
|
||||
my $header = "Content-Type: application/json\n";
|
||||
my $reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url,
|
||||
headers => $header,
|
||||
method => 'POST',
|
||||
data => $data,
|
||||
);
|
||||
# No response, declare as failed
|
||||
if (!defined($reply) || !$reply) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: Could not connect to porkbun.com.", $host);
|
||||
next;
|
||||
}
|
||||
if (!header_ok($host, $reply)) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: failed (%s)", $host, $reply);
|
||||
next;
|
||||
}
|
||||
# Strip header
|
||||
# Porkbun sends data in chunks, so it is assumed to be one chunk and parsed forcibly.
|
||||
$reply =~ qr/{(?:[^{}]*|(?R))*}/mp;
|
||||
my $response = eval { decode_json(${^MATCH}) };
|
||||
if (!defined($response)) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("%s -- Unexpected service response.", $host);
|
||||
next;
|
||||
}
|
||||
if ($response->{status} ne 'SUCCESS') {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("%s -- Unexpected status. (status = %s)", $host, $response->{status});
|
||||
next;
|
||||
}
|
||||
my $records = $response->{records};
|
||||
if (ref($records) eq 'ARRAY' && defined $records->[0]->{'id'}) {
|
||||
my $count = scalar(@{$records});
|
||||
if ($count > 1) {
|
||||
warning("updating %s: There are multiple applicable records. Only first record is used. Overwrite all with the same content.");
|
||||
}
|
||||
my $current_content = $records->[0]->{'content'};
|
||||
if ($current_content eq $ipv4) {
|
||||
$config{$host}{'status'} = "good";
|
||||
success("updating %s: skipped: IPv4 address was already set to %s.", $host, $ipv4);
|
||||
next;
|
||||
}
|
||||
my $ttl = $records->[0]->{'ttl'};
|
||||
my $notes = $records->[0]->{'notes'};
|
||||
debug("ttl = %s", $ttl);
|
||||
debug("notes = %s", $notes);
|
||||
$url = "https://porkbun.com/api/json/v3/dns/editByNameType/$domain/A/$sub_domain";
|
||||
$data = encode_json({
|
||||
secretapikey => $config{$host}{'secretapikey'},
|
||||
apikey => $config{$host}{'apikey'},
|
||||
content => $ipv4,
|
||||
ttl => $ttl,
|
||||
notes => $notes,
|
||||
});
|
||||
$reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url,
|
||||
headers => $header,
|
||||
method => 'POST',
|
||||
data => $data,
|
||||
);
|
||||
# No response, declare as failed
|
||||
if (!defined($reply) || !$reply) {
|
||||
failed("updating %s: Could not connect to porkbun.com.", $host);
|
||||
next;
|
||||
}
|
||||
if (!header_ok($host, $reply)) {
|
||||
failed("updating %s: failed (%s)", $host, $reply);
|
||||
next;
|
||||
}
|
||||
$config{$host}{'status'} = "good";
|
||||
success("updating %s: good: IPv4 address set to %s", $host, $ipv4);
|
||||
next;
|
||||
} else {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: No applicable existing records.", $host);
|
||||
next;
|
||||
}
|
||||
} else {
|
||||
info("No IPv4 address for %s", $host);
|
||||
}
|
||||
if (is_ipv6($ipv6)) {
|
||||
info("setting IPv6 address to %s for %s", $ipv6, $host);
|
||||
verbose("UPDATE:","updating %s", $host);
|
||||
|
||||
my $url = "https://porkbun.com/api/json/v3/dns/retrieveByNameType/$domain/AAAA/$sub_domain";
|
||||
my $data = encode_json({
|
||||
secretapikey => $config{$host}{'secretapikey'},
|
||||
apikey => $config{$host}{'apikey'},
|
||||
});
|
||||
my $header = "Content-Type: application/json\n";
|
||||
my $reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url,
|
||||
headers => $header,
|
||||
method => 'POST',
|
||||
data => $data,
|
||||
);
|
||||
# No response, declare as failed
|
||||
if (!defined($reply) || !$reply) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: Could not connect to porkbun.com.", $host);
|
||||
next;
|
||||
}
|
||||
if (!header_ok($host, $reply)) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: failed (%s)", $host, $reply);
|
||||
next;
|
||||
}
|
||||
# Strip header
|
||||
# Porkbun sends data in chunks, so it is assumed to be one chunk and parsed forcibly.
|
||||
$reply =~ qr/{(?:[^{}]*|(?R))*}/mp;
|
||||
my $response = eval { decode_json(${^MATCH}) };
|
||||
if (!defined($response)) {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("%s -- Unexpected service response.", $host);
|
||||
next;
|
||||
}
|
||||
if ($response->{status} ne 'SUCCESS') {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("%s -- Unexpected status. (status = %s)", $host, $response->{status});
|
||||
next;
|
||||
}
|
||||
my $records = $response->{records};
|
||||
if (ref($records) eq 'ARRAY' && defined $records->[0]->{'id'}) {
|
||||
my $count = scalar(@{$records});
|
||||
if ($count > 1) {
|
||||
warning("updating %s: There are multiple applicable records. Only first record is used. Overwrite all with the same content.");
|
||||
}
|
||||
my $current_content = $records->[0]->{'content'};
|
||||
if ($current_content eq $ipv6) {
|
||||
$config{$host}{'status'} = "good";
|
||||
success("updating %s: skipped: IPv6 address was already set to %s.", $host, $ipv6);
|
||||
next;
|
||||
}
|
||||
my $ttl = $records->[0]->{'ttl'};
|
||||
my $notes = $records->[0]->{'notes'};
|
||||
debug("ttl = %s", $ttl);
|
||||
debug("notes = %s", $notes);
|
||||
$url = "https://porkbun.com/api/json/v3/dns/editByNameType/$domain/AAAA/$sub_domain";
|
||||
$data = encode_json({
|
||||
secretapikey => $config{$host}{'secretapikey'},
|
||||
apikey => $config{$host}{'apikey'},
|
||||
content => $ipv6,
|
||||
ttl => $ttl,
|
||||
notes => $notes,
|
||||
});
|
||||
$reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url,
|
||||
headers => $header,
|
||||
method => 'POST',
|
||||
data => $data,
|
||||
);
|
||||
# No response, declare as failed
|
||||
if (!defined($reply) || !$reply) {
|
||||
failed("updating %s: Could not connect to porkbun.com.", $host);
|
||||
next;
|
||||
}
|
||||
if (!header_ok($host, $reply)) {
|
||||
failed("updating %s: failed (%s)", $host, $reply);
|
||||
next;
|
||||
}
|
||||
$config{$host}{'status'} = "good";
|
||||
success("updating %s: good: IPv6 address set to %s", $host, $ipv4);
|
||||
next;
|
||||
} else {
|
||||
$config{$host}{'status'} = "bad";
|
||||
failed("updating %s: No applicable existing records.", $host);
|
||||
next;
|
||||
}
|
||||
} else {
|
||||
info("No IPv6 address for %s", $host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7389,6 +7905,90 @@ sub nic_regfishde_update {
|
|||
}
|
||||
}
|
||||
|
||||
######################################################################
|
||||
######################################################################
|
||||
## enom
|
||||
######################################################################
|
||||
sub nic_enom_examples {
|
||||
return <<EoEXAMPLE;
|
||||
o 'enom'
|
||||
The 'enom' protocol is used by DNS services offered by www.enom.com and their resellers.
|
||||
Configuration variables applicable to the 'enom' protocol are:
|
||||
protocol=enom ##
|
||||
server=fqdn.of.service ## defaults to dynamic.name-services.com
|
||||
login=domain.name ## base domain name
|
||||
password=domain-password ## the domain password registered with the service
|
||||
A_record ## the A record(s) registered with the service
|
||||
Example ${program}.conf file entries:
|
||||
## single host update
|
||||
protocol=enom, \\
|
||||
login=mydomain.com, \\
|
||||
password=mydomain.com-password \\
|
||||
www
|
||||
## multiple host update
|
||||
protocol=enom, \\
|
||||
login=mydomain.com, \\
|
||||
password=mydomain.com-password \\
|
||||
www,mail,*
|
||||
EoEXAMPLE
|
||||
}
|
||||
######################################################################
|
||||
## enom_update
|
||||
##
|
||||
## written by Lars Fredriksson
|
||||
## modified by Leonidas Arvanitis
|
||||
##
|
||||
## based on http://www.edoceo.com/creo/enomddu.php
|
||||
##
|
||||
## needs this url to update:
|
||||
## http://dynamic.name-services.com/interface.asp?Command=SetDNSHost&HostName=www
|
||||
## &Zone=mydomain.com&DomainPassword=MyD0mainPa55w0rD&Address=123.45.678.90
|
||||
##
|
||||
######################################################################
|
||||
sub nic_enom_update {
|
||||
debug("\nenom_update -------------------");
|
||||
## 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);
|
||||
|
||||
my $url;
|
||||
$url = "https://$config{$h}{'server'}/interface.asp?Command=SetDNSHost";
|
||||
$url .= "&HostName=$h";
|
||||
$url .= "&Zone=$config{$h}{'login'}";
|
||||
$url .= "&DomainPassword=$config{$h}{'password'}";
|
||||
$url .= "&Address=";
|
||||
$url .= $ip if $ip;
|
||||
|
||||
my $reply = geturl(
|
||||
proxy => opt('proxy'),
|
||||
url => $url
|
||||
);
|
||||
|
||||
if (!defined($reply) || !$reply) {
|
||||
failed("updating %s: Could not connect to %s.", $h, $config{$h}{'server'});
|
||||
last;
|
||||
}
|
||||
|
||||
last if !header_ok($h, $reply);
|
||||
|
||||
my @reply = split /\n/, $reply;
|
||||
|
||||
if (grep /Done=true/i, @reply) {
|
||||
$config{$h}{'ip'} = $ip;
|
||||
$config{$h}{'mtime'} = $now;
|
||||
$config{$h}{'status'} = 'good';
|
||||
success("updating %s: good: IP address set to %s", $h, $ip);
|
||||
} else {
|
||||
$config{$h}{'status'} = 'failed';
|
||||
warning("SENT: %s", $url) unless opt('verbose');
|
||||
warning("REPLIED: %s", $reply);
|
||||
failed("updating %s: Invalid reply.", $h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Execute main() if this file is run as a script or run via PAR (https://metacpan.org/pod/PAR),
|
||||
# otherwise do nothing. This "modulino" pattern makes it possible to import this file as a module
|
||||
# and test its functions directly; there's no need for test-only command-line arguments or stdout
|
||||
|
|
|
|||
|
|
@ -1,31 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# PROVIDE: ddclient
|
||||
# REQUIRE: LOGIN
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf.local or /etc/rc.conf
|
||||
# to enable this service:
|
||||
#
|
||||
# ddclient_enable (bool): Set to NO by default.
|
||||
# Set it to YES to enable ddclient.
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name=ddclient
|
||||
rcvar=ddclient_enable
|
||||
ddclient_conf="/etc/ddclient/ddclient.conf"
|
||||
|
||||
command="/usr/local/sbin/${name}"
|
||||
load_rc_config $name
|
||||
|
||||
delay=$(grep -v '^\s*#' "${ddclient_conf}" | grep -i -m 1 "daemon" | awk -F '=' '{print $2}')
|
||||
|
||||
if [ -z "${delay}" ]
|
||||
then
|
||||
ddclient_flags="-daemon 300"
|
||||
else
|
||||
ddclient_flags=""
|
||||
fi
|
||||
|
||||
run_rc_command "$1"
|
||||
|
|
@ -1,100 +0,0 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# ddclient This shell script takes care of starting and stopping
|
||||
# ddclient.
|
||||
#
|
||||
# chkconfig: 2345 65 35
|
||||
# description: ddclient provides support for updating dynamic DNS services.
|
||||
|
||||
CONF=/etc/ddclient/ddclient.conf
|
||||
program=ddclient
|
||||
|
||||
[ -f $CONF ] || exit 0
|
||||
|
||||
system=unknown
|
||||
if [ -f /etc/fedora-release ]; then
|
||||
system=fedora
|
||||
elif [ -f /etc/redhat-release ]; then
|
||||
system=redhat
|
||||
elif [ -f /etc/debian_version ]; then
|
||||
system=debian
|
||||
fi
|
||||
|
||||
PID=''
|
||||
if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then
|
||||
. /etc/init.d/functions
|
||||
PID=`pidofproc $program`
|
||||
else
|
||||
PID=`ps -aef | grep "$program - sleep" | grep -v grep | awk '{print $2}'`
|
||||
fi
|
||||
|
||||
PATH=/usr/bin:/usr/local/bin:${PATH}
|
||||
export PATH
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
# See if daemon=value is specified in the config file.
|
||||
# Assumptions:
|
||||
# * there are no quoted "#" characters before "daemon="
|
||||
# (if there is a "#" it starts a comment)
|
||||
# * "daemon=" does not appear in a password or value
|
||||
# * if the interval value is 0, it is not quoted
|
||||
INTERVAL=$(sed -e '
|
||||
s/^\([^#]*[,[:space:]]\)\{0,1\}daemon=\([^,[:space:]]*\).*$/\2/
|
||||
t quit
|
||||
d
|
||||
:quit
|
||||
q
|
||||
' "$CONF")
|
||||
if [ -z "$DELAY" ] || [ "$DELAY" = "0" ]; then
|
||||
DELAY="-daemon 300"
|
||||
else
|
||||
# use the interval specified in the config file
|
||||
DELAY=''
|
||||
fi
|
||||
echo -n "Starting ddclient: "
|
||||
if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then
|
||||
daemon $program $DELAY
|
||||
else
|
||||
ddclient $DELAY
|
||||
fi
|
||||
echo
|
||||
;;
|
||||
stop)
|
||||
# Stop daemon.
|
||||
echo -n "Shutting down ddclient: "
|
||||
if [ -n "$PID" ]; then
|
||||
if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then
|
||||
killproc $program
|
||||
else
|
||||
kill $PID
|
||||
fi
|
||||
else
|
||||
echo "ddclient is not running"
|
||||
fi
|
||||
echo
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
if [ "$system" = "fedora" ] || [ "$system" = "redhat" ]; then
|
||||
status $program
|
||||
else
|
||||
if test "$PID"; then
|
||||
for p in $PID; do
|
||||
echo "$program (pid $p) is running"
|
||||
done
|
||||
else
|
||||
echo "$program is stopped"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ddclient {start|stop|restart|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
#!/sbin/openrc-run
|
||||
description="ddclient Daemon for Alpine"
|
||||
command="/usr/bin/ddclient"
|
||||
config_file="/etc/ddclient/ddclient.conf"
|
||||
command_args=""
|
||||
pidfile=$(grep -v '^\s*#' "${config_file}" | grep -i -m 1 pid= | awk -F '=' '{print $2}')
|
||||
delay=$(grep -v '^\s*#' "${config_file}" | grep -i -m 1 "daemon" | awk -F '=' '{print $2}')
|
||||
|
||||
if [ -z "${delay}" ]
|
||||
then
|
||||
command_args="-daemon 300"
|
||||
else
|
||||
command_args=""
|
||||
fi
|
||||
|
||||
|
||||
depend() {
|
||||
use logger
|
||||
need net
|
||||
after firewall
|
||||
}
|
||||
|
||||
start() {
|
||||
ebegin "Starting ddclient"
|
||||
start-stop-daemon --start \
|
||||
--exec "${command}" \
|
||||
--pidfile "${pidfile}" \
|
||||
-- \
|
||||
${command_args}
|
||||
eend $?
|
||||
}
|
||||
|
||||
stop() {
|
||||
ebegin "Stopping ddclient"
|
||||
start-stop-daemon --stop --exec "${command}" \
|
||||
--pidfile "${pidfile}"
|
||||
eend $?
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ddclient This shell script takes care of starting and stopping
|
||||
# ddclient.
|
||||
#
|
||||
# chkconfig: 2345 65 35
|
||||
# description: ddclient provides support for updating dynamic DNS services.
|
||||
#
|
||||
# Above is for RedHat and now the LSB part
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ddclient
|
||||
# Required-Start: $syslog $remote_fs
|
||||
# Should-Start: $time ypbind sendmail
|
||||
# Required-Stop: $syslog $remote_fs
|
||||
# Should-Stop: $time ypbind sendmail
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: ddclient provides support for updating dynamic DNS services
|
||||
# Description: ddclient is a Perl client used to update dynamic DNS
|
||||
# entries for accounts on many dynamic DNS services and
|
||||
# can be used on many types of firewalls
|
||||
### END INIT INFO
|
||||
#
|
||||
###
|
||||
|
||||
[ -f /etc/ddclient/ddclient.conf ] || exit 0
|
||||
|
||||
DDCLIENT_BIN=/usr/bin/ddclient
|
||||
|
||||
#
|
||||
# LSB Standard (SuSE,RedHat,...)
|
||||
#
|
||||
if [ -f /lib/lsb/init-functions ] ; then
|
||||
. /lib/lsb/init-functions
|
||||
fi
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting ddclient "
|
||||
start_daemon $DDCLIENT_BIN -daemon 300
|
||||
rc_status -v
|
||||
;;
|
||||
stop)
|
||||
echo -n "Shutting down ddclient "
|
||||
killproc -TERM `basename $DDCLIENT_BIN`
|
||||
rc_status -v
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
rc_status
|
||||
;;
|
||||
status)
|
||||
echo -n "Checking for service ddclient "
|
||||
checkproc `basename $DDCLIENT_BIN`w
|
||||
rc_status -v
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ddclient {start|stop|restart|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# ddclient This shell script takes care of starting and stopping
|
||||
# ddclient.
|
||||
#
|
||||
# chkconfig: 2345 65 35
|
||||
# description: ddclient provides support for updating dynamic DNS services.
|
||||
|
||||
[ -f /etc/ddclient/ddclient.conf ] || exit 0
|
||||
|
||||
. /etc/rc.d/init.d/functions
|
||||
|
||||
# See how we were called.
|
||||
case "$1" in
|
||||
start)
|
||||
# Start daemon.
|
||||
echo -n "Starting ddclient: "
|
||||
touch /var/lock/subsys/ddclient
|
||||
daemon ddclient -daemon 300
|
||||
echo
|
||||
;;
|
||||
stop)
|
||||
# Stop daemon.
|
||||
echo -n "Shutting down ddclient: "
|
||||
killproc ddclient
|
||||
echo
|
||||
rm -f /var/lock/subsys/ddclient
|
||||
;;
|
||||
restart)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
status)
|
||||
status ddclient
|
||||
;;
|
||||
*)
|
||||
echo "Usage: ddclient {start|stop|restart|status}"
|
||||
exit 1
|
||||
esac
|
||||
|
||||
exit 0
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: ddclient
|
||||
# Required-Start: $remote_fs $syslog $network
|
||||
# Required-Stop: $remote_fs $syslog $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: Start ddclient daemon at boot time
|
||||
# Description: Start ddclient that provides support for updating dynamic DNS services. Originally submitted by paolo martinelli, updated by joe passavanti
|
||||
### END INIT INFO
|
||||
|
||||
DDCLIENT=/usr/bin/ddclient
|
||||
CONF=/etc/ddclient/ddclient.conf
|
||||
PIDFILE=/var/run/ddclient.pid
|
||||
|
||||
test -x $DDCLIENT || exit 0
|
||||
test -f $CONF || exit 0
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ ! -f $PIDFILE ]; then
|
||||
log_begin_msg "Starting ddclient..."
|
||||
DELAY=`grep -v '^\s*#' $CONF | grep -i -m 1 "daemon" | awk -F '=' '{print $2}'`
|
||||
if [ -z "$DELAY" ] ; then
|
||||
DELAY="-daemon 300"
|
||||
else
|
||||
DELAY=''
|
||||
fi
|
||||
start-stop-daemon -S -q -p $PIDFILE -x $DDCLIENT -- $DELAY
|
||||
log_end_msg $?
|
||||
else
|
||||
log_warning_msg "Service ddclient already running..."
|
||||
fi
|
||||
;;
|
||||
stop)
|
||||
if [ -f $PIDFILE ] ; then
|
||||
log_begin_msg "Stopping ddclient..."
|
||||
start-stop-daemon -K -q -p $PIDFILE
|
||||
log_end_msg $?
|
||||
rm -f $PIDFILE
|
||||
else
|
||||
log_warning_msg "No ddclient running..."
|
||||
fi
|
||||
;;
|
||||
restart|reload|force-reload)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
*)
|
||||
log_success_msg "Usage: $0 {start|stop|restart|reload|force-reload}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in a new issue