Commit 8f15ca00 authored by Franco Fichtner's avatar Franco Fichtner

dyndns: move to plugins

parent 7884e345
......@@ -33,9 +33,6 @@
/usr/local/etc/inc/notices.smtp.inc
/usr/local/etc/inc/plugins.inc
/usr/local/etc/inc/plugins.inc.d/dnsmasq.inc
/usr/local/etc/inc/plugins.inc.d/dyndns.inc
/usr/local/etc/inc/plugins.inc.d/dyndns/phpDynDNS.inc
/usr/local/etc/inc/plugins.inc.d/dyndns/r53.inc
/usr/local/etc/inc/plugins.inc.d/ipfw.inc
/usr/local/etc/inc/plugins.inc.d/ipsec.inc
/usr/local/etc/inc/plugins.inc.d/ipsec/auth-user.php
......@@ -82,7 +79,6 @@
/usr/local/etc/rc.d/configd
/usr/local/etc/rc.d/flowd_aggregate
/usr/local/etc/rc.d/netflow
/usr/local/etc/rc.dyndns
/usr/local/etc/rc.expireaccounts
/usr/local/etc/rc.filter_configure
/usr/local/etc/rc.filter_synchronize
......@@ -454,8 +450,6 @@
/usr/local/opnsense/mvc/app/models/OPNsense/Diagnostics/Netflow.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Dnsmasq/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/Dnsmasq/Menu/Menu.xml
/usr/local/opnsense/mvc/app/models/OPNsense/DynamicDNS/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/DynamicDNS/Menu/Menu.xml
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/ACL/ACL.xml
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/IDS.php
/usr/local/opnsense/mvc/app/models/OPNsense/IDS/IDS.xml
......@@ -641,7 +635,6 @@
/usr/local/opnsense/service/conf/actions.d/actions_cron.conf
/usr/local/opnsense/service/conf/actions.d/actions_dhcpd.conf
/usr/local/opnsense/service/conf/actions.d/actions_dns.conf
/usr/local/opnsense/service/conf/actions.d/actions_dyndns.conf
/usr/local/opnsense/service/conf/actions.d/actions_filter.conf
/usr/local/opnsense/service/conf/actions.d/actions_firmware.conf
/usr/local/opnsense/service/conf/actions.d/actions_ids.conf
......@@ -1060,8 +1053,6 @@
/usr/local/www/services_dnsmasq.php
/usr/local/www/services_dnsmasq_domainoverride_edit.php
/usr/local/www/services_dnsmasq_edit.php
/usr/local/www/services_dyndns.php
/usr/local/www/services_dyndns_edit.php
/usr/local/www/services_ntpd.php
/usr/local/www/services_ntpd_gps.php
/usr/local/www/services_ntpd_pps.php
......@@ -1129,7 +1120,6 @@
/usr/local/www/widgets/api/plugins/temperature.inc
/usr/local/www/widgets/api/plugins/traffic.inc
/usr/local/www/widgets/include/carp_status.inc
/usr/local/www/widgets/include/dyn_dns_status.inc
/usr/local/www/widgets/include/gateways.inc
/usr/local/www/widgets/include/interface_statistics.inc
/usr/local/www/widgets/include/interfaces.inc
......@@ -1142,7 +1132,6 @@
/usr/local/www/widgets/include/thermal_sensors.inc
/usr/local/www/widgets/include/traffic_graph.inc
/usr/local/www/widgets/widgets/carp_status.widget.php
/usr/local/www/widgets/widgets/dyn_dns_status.widget.php
/usr/local/www/widgets/widgets/gateways.widget.php
/usr/local/www/widgets/widgets/interface_list.widget.php
/usr/local/www/widgets/widgets/interface_statistics.widget.php
......
<?php
/*
Copyright (C) 2014-2017 Franco Fichtner <franco@opnsense.org>
Copyright (C) 2010 Ermal Luci
Copyright (C) 2005-2006 Colin Smith <ethethlay@gmail.com>
Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once('plugins.inc.d/dyndns/phpDynDNS.inc');
require_once('plugins.inc.d/dyndns/r53.inc');
function dyndns_configure()
{
return array(
'bootup' => array('dyndns_configure_do'),
'local' => array('dyndns_configure_do'),
'newwanip' => array('dyndns_configure_do:2'),
);
}
function dyndns_enabled()
{
global $config;
if (isset($config['dyndnses']['dyndns'])) {
foreach ($config['dyndnses']['dyndns'] as $conf) {
if (isset($conf['enable'])) {
return true;
}
}
}
return false;
}
function dyndns_services()
{
global $config;
$services = array();
if (dyndns_enabled()) {
$services[] = array(
'description' => gettext('Dynamic DNS'),
'configd' => array(
'restart' => array('dyndns reload'),
),
'nocheck' => true,
'name' => 'dyndns',
);
}
return $services;
}
function dyndns_cron()
{
$jobs = array();
if (dyndns_enabled()) {
$jobs[]['autocron'] = array('/usr/local/etc/rc.dyndns', '11', '1');
}
return $jobs;
}
function dyndns_list()
{
/*
* XXX something like this would be cool:
*
* https://github.com/openwrt/packages/blob/master/net/ddns-scripts/files/services
*/
return array(
'3322' => '3322',
'citynetwork' => 'City Network',
'cloudflare' => 'CloudFlare',
'custom' => 'Custom',
'custom-v6' => 'Custom (v6)',
'dhs' => 'DHS',
'dnsexit' => 'DNSexit',
'dnsomatic' => 'DNS-O-Matic',
'duckdns' => 'Duck DNS',
'dyndns' => 'DynDNS (dynamic)',
'dyndns-custom' => 'DynDNS (custom)',
'dyndns-static' => 'DynDNS (static)',
'dyns' => 'DyNS',
'easydns' => 'easyDNS',
'eurodns' => 'EuroDNS',
'freedns' => 'freeDNS',
'googledomains' => 'Google Domains',
'gratisdns' => 'GratisDNS',
'he-net' => 'HE.net',
'he-net-tunnelbroker' => 'HE.net Tunnelbroker',
'he-net-v6' => 'HE.net (v6)',
'loopia' => 'Loopia',
'namecheap' => 'Namecheap',
'noip' => 'No-IP',
'noip-free' => 'No-IP (free)',
'ods' => 'ODS.org',
'opendns' => 'OpenDNS',
'oray' => 'Oray',
'ovh-dynhost' => 'OVH DynHOST',
'route53' => 'Route 53',
'selfhost' => 'SelfHost',
'strato' => 'STRATO',
'zoneedit' => 'ZoneEdit',
);
}
function dyndns_cache_file($conf, $ipver = 4)
{
$ipver = $ipver == 6 ? '_v6' : '';
return "/var/cache/dyndns_{$conf['interface']}_{$conf['host']}_{$conf['id']}{$ipver}.cache";
}
function dyndns_configure_client($conf)
{
if (!isset($conf['enable'])) {
return;
}
$dns = new updatedns($dnsService = $conf['type'],
$dnsHost = $conf['host'],
$dnsUser = $conf['username'],
$dnsPass = $conf['password'],
$dnsWilcard = $conf['wildcard'],
$dnsMX = $conf['mx'],
$dnsIf = "{$conf['interface']}",
$dnsBackMX = NULL,
$dnsServer = NULL,
$dnsPort = NULL,
$dnsUpdateURL = "{$conf['updateurl']}",
$forceUpdate = $conf['force'],
$dnsZoneID=$conf['zoneid'],
$dnsTTL=$conf['ttl'],
$dnsResultMatch = "{$conf['resultmatch']}",
$dnsRequestIf = "{$conf['requestif']}",
$dnsID = "{$conf['id']}",
$dnsVerboseLog = $conf['verboselog'],
$curlIpresolveV4 = $conf['curl_ipresolve_v4'],
$curlSslVerifypeer = $conf['curl_ssl_verifypeer']
);
}
function dyndns_configure_do($verbose = false, $int = '')
{
global $config;
if (!dyndns_enabled()) {
return;
}
$dyndnscfg = $config['dyndnses']['dyndns'];
$gwgroups = return_gateway_groups_array();
if ($verbose) {
echo 'Configuring dynamic DNS clients...';
flush();
}
foreach ($dyndnscfg as $dyndns) {
if ((empty($int)) || ($int == $dyndns['interface']) || (is_array($gwgroups[$dyndns['interface']]))) {
$dyndns['verboselog'] = isset($dyndns['verboselog']);
$dyndns['curl_ipresolve_v4'] = isset($dyndns['curl_ipresolve_v4']);
$dyndns['curl_ssl_verifypeer'] = isset($dyndns['curl_ssl_verifypeer']);
dyndns_configure_client($dyndns);
sleep(1);
}
}
if ($verbose) {
echo "done.\n";
}
}
<?php
/*
* PHP.updateDNS (OPNsense version)
*
* +====================================================+
* Services Supported:
* - DynDns (dyndns.org) [dynamic, static, custom]
* - DHSDns (dhs.org)
* - No-IP (no-ip.com)
* - EasyDNS (easydns.com)
* - DHS (www.dhs.org)
* - HN (hn.org) -- incomplete checking!
* - DynS (dyns.org)
* - ZoneEdit (zoneedit.com)
* - FreeDNS (freedns.afraid.org)
* - Loopia (loopia.se)
* - StaticCling (staticcling.org)
* - DNSexit (dnsexit.com)
* - OpenDNS (opendns.com)
* - Namecheap (namecheap.com)
* - HE.net (dns.he.net)
* - HE.net IPv6 (dns.he.net)
* - HE.net Tunnelbroker IP update (ipv4.tunnelbroker.net)
* - SelfHost (selfhost.de)
* - Amazon Route53 (aws.amazon.com)
* - DNS-O-Matic (dnsomatic.com)
* - Custom dynamic DNS (any URL)
* - Custom dynamic DNS IPv6 (any URL)
* - CloudFlare (www.cloudflare.com)
* - Eurodns (eurodns.com)
* - GratisDNS (gratisdns.dk)
* - City Network (citynetwork.se)
* - Duck DNS (duckdns.org)
* - Google Domains (domains.google.com)
* - STRATO (strato.com)
* - 3322 (3322.net)
* - Oray (oray.com)
* +----------------------------------------------------+
* Requirements:
* - PHP version 4.0.2 or higher with the CURL Library and the PCRE Library
* +----------------------------------------------------+
* Public Functions
* - updatedns()
*
* Private Functions
* - _update()
* - _checkStatus()
* - _error()
* - _detectChange()
* - _debug()
* - _checkIP()
* +----------------------------------------------------+
* DynDNS Dynamic - Last Tested: 12 July 2005
* DynDNS Static - Last Tested: NEVER
* DynDNS Custom - Last Tested: NEVER
* No-IP - Last Tested: 20 July 2008
* HN.org - Last Tested: 12 July 2005
* EasyDNS - Last Tested: 20 July 2008
* DHS - Last Tested: 12 July 2005
* ZoneEdit - Last Tested: NEVER
* Dyns - Last Tested: NEVER
* ODS - Last Tested: 02 August 2005
* FreeDNS - Last Tested: 23 Feb 2011
* Loopia - Last Tested: NEVER
* StaticCling - Last Tested: 27 April 2006
* DNSexit - Last Tested: 20 July 2008
* OpenDNS - Last Tested: 4 August 2008
* Namecheap - Last Tested: 31 August 2010
* HE.net - Last Tested: 7 July 2013
* HE.net IPv6 - Last Tested: 7 July 2013
* HE.net Tunnel - Last Tested: 28 June 2011
* SelfHost - Last Tested: 26 December 2011
* Amazon Route53 - Last tested: 01 April 2012
* DNS-O-Matic - Last Tested: 9 September 2010
* CloudFlare - Last Tested: 30 May 2013
* Eurodns - Last Tested: 27 June 2013
* GratisDNS - Last Tested: 15 August 2012
* OVH DynHOST - Last Tested: NEVER
* City Network - Last Tested: 13 November 2013
* Duck DNS - Last Tested: 04 March 2015
* Google Domains - Last Tested: 20 February 2017
* STRATO - Last Tested: 09 May 2017
* 3322 - Last Tested: 26 May 2017
* Oray - Last Tested: 26 May 2017
* +====================================================+
*
* @author E.Kristensen
* @link http://www.idylldesigns.com/projects/phpdns/
* @version 0.8
* @updated 13 October 05 at 21:02:42 GMT
*
* DNSexit/OpenDNS support and multiwan extension for pfSense by Ermal Luci
* Custom DNS support by Matt Corallo
*/
class updatedns {
var $_cacheFile;
var $_cacheFile_v6;
var $_debugFile;
var $_UserAgent = 'User-Agent: phpDynDNS/0.7';
var $_errorVerbosity = 0;
var $_dnsService;
var $_dnsUser;
var $_dnsPass;
var $_dnsHost;
var $_dnsIP;
var $_dnsWildcard;
var $_dnsMX;
var $_dnsBackMX;
var $_dnsServer;
var $_dnsPort;
var $_dnsUpdateURL;
var $_dnsZoneID;
var $_dnsTTL;
var $status;
var $_debugID;
var $_if;
var $_dnsResultMatch;
var $_dnsRequestIf;
var $_dnsRequestIfIP;
var $_dnsVerboseLog;
var $_curlIpresolveV4;
var $_curlSslVerifypeer;
var $_dnsMaxCacheAgeDays;
var $_dnsDummyUpdateDone;
var $_forceUpdateNeeded;
var $_useIPv6;
/*
* Public Constructor Function (added 12 July 05) [beta]
* - Gets the dice rolling for the update.
* - $dnsResultMatch should only be used with $dnsService = 'custom'
* - $dnsResultMatch is parsed for '%IP%', which is the IP the provider was updated to,
* - it is otherwise expected to be exactly identical to what is returned by the Provider.
* - $dnsUser, and $dnsPass indicate HTTP Auth for custom DNS, if they are needed in the URL (GET Variables), include them in $dnsUpdateURL.
* - $For custom requests, $dnsUpdateURL is parsed for '%IP%', which is replaced with the new IP.
*/
public function __construct ($dnsService = '', $dnsHost = '', $dnsUser = '', $dnsPass = '',
$dnsWildcard = 'OFF', $dnsMX = '', $dnsIf = '', $dnsBackMX = '',
$dnsServer = '', $dnsPort = '', $dnsUpdateURL = '', $forceUpdate = false,
$dnsZoneID ='', $dnsTTL='', $dnsResultMatch = '', $dnsRequestIf = '',
$dnsID = '', $dnsVerboseLog = false, $curlIpresolveV4 = false, $curlSslVerifypeer = true) {
/* XXX because the call stack is upside down we need to reassemble config parts here... */
$conf = array('host' => $dnsHost, 'id' => $dnsID, 'interface' => $dnsIf);
$this->_cacheFile = dyndns_cache_file($conf, 4);
$this->_cacheFile_v6 = dyndns_cache_file($conf, 6);
$this->_debugFile = dyndns_cache_file($conf, 4) . '.debug';
$this->_curlIpresolveV4 = $curlIpresolveV4;
$this->_curlSslVerifypeer = $curlSslVerifypeer;
$this->_dnsVerboseLog = $dnsVerboseLog;
if ($this->_dnsVerboseLog)
log_error("Dynamic DNS: updatedns() starting");
$dyndnslck = lock("DDNS".$dnsID, LOCK_EX);
if (!$dnsService) $this->_error(2);
switch ($dnsService) {
case 'freedns':
if (!$dnsHost) $this->_error(5);
break;
case 'namecheap':
if (!$dnsPass) $this->_error(4);
if (!$dnsHost) $this->_error(5);
break;
case 'route53':
if (!$dnsZoneID) $this->_error(8);
if (!$dnsTTL) $this->_error(9);
break;
case 'custom':
if (!$dnsUpdateURL) $this->_error(7);
break;
case 'duckdns':
if (!$dnsUser) $this->_error(3);
if (!$dnsHost) $this->_error(5);
break;
default:
if (!$dnsUser) $this->_error(3);
if (!$dnsPass) $this->_error(4);
if (!$dnsHost) $this->_error(5);
break;
}
switch ($dnsService) {
case 'he-net-v6':
case 'custom-v6':
$this->_useIPv6 = true;
break;
default:
$this->_useIPv6 = false;
}
$this->_dnsService = strtolower($dnsService);
$this->_dnsUser = $dnsUser;
$this->_dnsPass = $dnsPass;
$this->_dnsHost = $dnsHost;
$this->_dnsServer = $dnsServer;
$this->_dnsPort = $dnsPort;
$this->_dnsWildcard = $dnsWildcard;
$this->_dnsMX = $dnsMX;
$this->_dnsZoneID = $dnsZoneID;
$this->_dnsTTL = $dnsTTL;
$this->_if = get_failover_interface($dnsIf);
$this->_checkIP();
$this->_dnsUpdateURL = $dnsUpdateURL;
$this->_dnsResultMatch = $dnsResultMatch;
$this->_dnsRequestIf = get_failover_interface($dnsRequestIf);
if ($this->_dnsVerboseLog)
log_error("Dynamic DNS ({$this->_dnsHost}): running get_failover_interface for {$dnsRequestIf}. found {$this->_dnsRequestIf}");
$this->_dnsRequestIfIP = get_interface_ip($dnsRequestIf);
$this->_dnsMaxCacheAgeDays = 25;
$this->_dnsDummyUpdateDone = false;
$this->_forceUpdateNeeded = $forceUpdate;
// Ensure that we were able to lookup the IP
if(!is_ipaddr($this->_dnsIP)) {
log_error("Dynamic DNS ({$this->_dnsHost}) There was an error trying to determine the public IP for interface - {$dnsIf}({$this->_if}). Probably interface is not a WAN interface.");
unlock($dyndnslck);
return;
}
$this->_debugID = rand(1000000, 9999999);
if ($forceUpdate == false && $this->_detectChange() == false) {
$this->_error(10);
} else {
switch ($this->_dnsService) {
case '3322':
case 'citynetwork':
case 'cloudflare':
case 'custom':
case 'custom-v6':
case 'dhs':
case 'dnsexit':
case 'dnsomatic':
case 'duckdns':
case 'dyndns':
case 'dyndns-custom':
case 'dyndns-static':
case 'dyns':
case 'easydns':
case 'eurodns':
case 'freedns':
case 'googledomains':
case 'gratisdns':
case 'he-net':
case 'he-net-tunnelbroker':
case 'he-net-v6':
case 'hn':
case 'loopia':
case 'namecheap':
case 'noip':
case 'noip-free':
case 'ods':
case 'opendns':
case 'ovh-dynhost':
case 'oray':
case 'route53':
case 'selfhost':
case 'strato':
case 'staticcling':
case 'zoneedit':
$this->_update();
if($this->_dnsDummyUpdateDone == true) {
// If a dummy update was needed, then sleep a while and do the update again to put the proper address back.
// Some providers (e.g. No-IP free accounts) need to have at least 1 address change every month.
// If the address has not changed recently, or the user did "Force Update", then the code does
// a dummy address change for providers like this.
sleep(10);
$this->_update();
}
break;
default:
$this->_error(6);
break;
}
}
unlock($dyndnslck);
}
/*
* Private Function (added 12 July 05) [beta]
* Send Update To Selected Service.
*/
function _update() {
if ($this->_dnsVerboseLog)
log_error("Dynamic DNS ({$this->_dnsHost}): _update() starting.");
if ($this->_dnsService != 'ods' and $this->_dnsService != 'route53 ') {
$ch = curl_init();
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, $this->_UserAgent);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_INTERFACE, $this->_dnsRequestIfIP);
curl_setopt($ch, CURLOPT_TIMEOUT, 120); // Completely empirical
}
switch ($this->_dnsService) {
case 'dyndns':
case 'dyndns-static':
case 'dyndns-custom':
if ($this->_dnsVerboseLog)
log_error("Dynamic DNS: ({$this->_dnsHost}) DNS update() starting.");
if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://members.dyndns.org/nic/update";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
break;
case 'dhs':
$post_data['hostscmd'] = 'edit';
$post_data['hostscmdstage'] = '2';
$post_data['type'] = '4';
$post_data['updatetype'] = 'Online';
$post_data['mx'] = $this->_dnsMX;
$post_data['mx2'] = '';
$post_data['txt'] = '';
$post_data['offline_url'] = '';
$post_data['cloak'] = 'Y';
$post_data['cloak_title'] = '';
$post_data['ip'] = $this->_dnsIP;
$post_data['domain'] = 'dyn.dhs.org';
$post_data['hostname'] = $this->_dnsHost;
$post_data['submit'] = 'Update';
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$server = "https://members.dhs.org/nic/hosts";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, '{$server}{$port}');
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
break;
case 'noip':
case 'noip-free':
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$server = "https://dynupdate.no-ip.com/ducupdate.php";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
if(($this->_dnsService == "noip-free") &&
($this->_forceUpdateNeeded == true) &&
($this->_dnsDummyUpdateDone == false)) {
// Update the IP to a dummy value to force No-IP free accounts to see a change.
$iptoset = "192.168.1.1";
$this->_dnsDummyUpdateDone = true;
log_error("Dynamic DNS ({$this->_dnsHost}): Processing dummy update on No-IP free account. IP temporarily set to " . $iptoset);
} else {
$iptoset = $this->_dnsIP;
}
curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&pass=' . urlencode($this->_dnsPass) . '&hostname=' . $this->_dnsHost.'&ip=' . $iptoset);
break;
case 'easydns':
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://members.easydns.com/dyn/dyndns.php";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server . $port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard=' . $this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=' . $this->_dnsBackMX);
break;
case 'hn':
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "http://dup.hn.org/vanity/update";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server . $port . '?ver=1&IP=' . $this->_dnsIP);
break;
case 'zoneedit':
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://dynamic.zoneedit.com/auth/dynamic.html";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, "{$server}{$port}?host=" .$this->_dnsHost);
break;
case 'dyns':
$server = "https://www.dyns.cx/postscript011.php";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server . $port . '?username=' . urlencode($this->_dnsUser) . '&password=' . $this->_dnsPass . '&host=' . $this->_dnsHost);
break;
case 'ods':
$misc_errno = 0;
$misc_error = "";
$server = "ods.org";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
$this->con['socket'] = fsockopen("{$server}{$port}", "7070", $misc_errno, $misc_error, 30);
/* Check that we have connected */
if (!$this->con['socket']) {
print "error! could not connect.";
break;
}
/* Here is the loop. Read the incoming data (from the socket connection) */
while (!feof($this->con['socket'])) {
$this->con['buffer']['all'] = trim(fgets($this->con['socket'], 4096));
$code = substr($this->con['buffer']['all'], 0, 3);
sleep(1);
switch($code) {
case 100:
fputs($this->con['socket'], "LOGIN ".$this->_dnsUser." ".$this->_dnsPass."\n");
break;
case 225:
fputs($this->con['socket'], "DELRR ".$this->_dnsHost." A\n");
break;
case 901:
fputs($this->con['socket'], "ADDRR ".$this->_dnsHost." A ".$this->_dnsIP."\n");
break;
case 795:
fputs($this->con['socket'], "QUIT\n");
break;
}
}
$this->_checkStatus(0, $code);
break;
case 'freedns':
curl_setopt($ch, CURLOPT_URL, 'https://freedns.afraid.org/dynamic/update.php?' . $this->_dnsPass);
break;
case 'dnsexit':
curl_setopt($ch, CURLOPT_URL, 'https://www.dnsexit.com/RemoteUpdate.sv?login='.$this->_dnsUser. '&password='.$this->_dnsPass.'&host='.$this->_dnsHost.'&myip='.$this->_dnsIP);
break;
case 'loopia':
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_URL, 'https://dns.loopia.se/XDynDNSServer/XDynDNS.php?hostname='.$this->_dnsHost.'&myip='.$this->_dnsIP);
break;
case 'opendns':
if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://updates.opendns.com/nic/update?hostname=". $this->_dnsHost;
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port);
break;
case 'staticcling':
curl_setopt($ch, CURLOPT_URL, 'https://www.staticcling.org/update.html?login='.$this->_dnsUser.'&pass='.$this->_dnsPass);
break;
case 'dnsomatic':
/* Example syntax
https://username:password@updates.dnsomatic.com/nic/update?hostname=yourhostname&myip=ipaddress&wildcard=NOCHG&mx=NOCHG&backmx=NOCHG
*/
if ($this->_dnsVerboseLog)
log_error("DNS-O-Matic: DNS update() starting.");
if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
/*
Reference: https://www.dnsomatic.com/wiki/api
DNS-O-Matic usernames are 3-25 characters.
DNS-O-Matic passwords are 6-20 characters.
All ASCII letters and numbers accepted.
Dots, dashes, and underscores allowed, but not at the beginning or end of the string.
Required: "rawurlencode" http://www.php.net/manual/en/function.rawurlencode.php
Encodes the given string according to RFC 3986.
*/
$server = "https://" . rawurlencode($this->_dnsUser) . ":" . rawurlencode($this->_dnsPass) . "@updates.dnsomatic.com/nic/update?hostname=";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NOCHG');
break;
case 'namecheap':
/* Example:
https://dynamicdns.park-your-domain.com/update?host=[host_name]&domain=[domain.com]&password=[domain_password]&ip=[your_ip]
*/
if ($this->_dnsVerboseLog)
log_error("Namecheap ({$this->_dnsHost}): DNS update() starting.");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
$dparts = explode(".", trim($this->_dnsHost));
$domain_part_count = ($dparts[count($dparts)-1] == "uk") ? 3 : 2;
$domain_offset = count($dparts) - $domain_part_count;
$hostname = implode(".", array_slice($dparts, 0, $domain_offset));
$domain = implode(".", array_slice($dparts, $domain_offset));
$dnspass = trim($this->_dnsPass);
$server = "https://dynamicdns.park-your-domain.com/update?host={$hostname}&domain={$domain}&password={$dnspass}&ip={$this->_dnsIP}";
curl_setopt($ch, CURLOPT_URL, $server);
break;
case 'he-net':
case 'he-net-v6':
if ($this->_dnsVerboseLog)
log_error("HE.net ({$this->_dnsHost}): DNS update() starting.");
$server = "https://dyn.dns.he.net/nic/update?";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
curl_setopt($ch, CURLOPT_URL, $server . 'hostname=' . $this->_dnsHost . '&password=' . $this->_dnsPass . '&myip=' . $this->_dnsIP);
break;
case 'he-net-tunnelbroker':
if ($this->_dnsVerboseLog)
log_error("HE.net Tunnelbroker: DNS update() starting.");
$server = "https://ipv4.tunnelbroker.net/ipv4_end.php?";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser . ':' . $this->_dnsPass);
curl_setopt($ch, CURLOPT_URL, $server . 'tid=' . $this->_dnsHost);
break;
case 'selfhost':
if ($this->_dnsVerboseLog)
log_error("SelfHost: DNS update() starting.");
if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://carol.selfhost.de/nic/update";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
break;
case 'route53':
if ($this->_dnsVerboseLog)
log_error("Route53 ({$this->_dnsHost}): DNS update() starting.");
/* Setting Variables */
$hostname = "{$this->_dnsHost}.";
$ZoneID = $this->_dnsZoneID;
$AccessKeyId=$this->_dnsUser;
$SecretAccessKey=$this->_dnsPass;
$NewIP=$this->_dnsIP;
$NewTTL=$this->_dnsTTL;
/* Set Amazon AWS Credentials for this record */
$r53 = new Route53($AccessKeyId, $SecretAccessKey);
/* Function to find old values of records in Route 53 */
if(!function_exists('Searchrecords')) {
function SearchRecords($records, $name) {
if (!is_array($records)) {
return false;
}
$result = array();
foreach($records as $record) {
if(strtolower($record['Name']) == strtolower($name)) {
$result [] = $record;
}
}
return ($result) ? $result : false;
}
}
$records = $r53->listResourceRecordSets("/hostedzone/$ZoneID");
/* Get IP for your hostname in Route 53 */
if(false !== ($a_result = SearchRecords($records['ResourceRecordSets'], "$hostname"))) {
$OldTTL=$a_result[0][TTL];
$OldIP=$a_result[0][ResourceRecords][0];
} else {
$OldIP="";
}
/* Check if we need to update DNS Record */
if ($OldIP !== $NewIP) {
if(!empty($OldIP)) {
/* Your Hostname already exists, deleting and creating it again */
$changes = array();
$changes[] = $r53->prepareChange(DELETE, $hostname, A, $OldTTL, $OldIP);
$changes[] = $r53->prepareChange(CREATE, $hostname, A, $NewTTL, $NewIP);
$result = $r53->changeResourceRecordSets("/hostedzone/$ZoneID", $changes);
} else {
/* Your Hostname does not exist yet, creating it */
$changes = $r53->prepareChange(CREATE, $hostname, A, $NewTTL, $NewIP);
$result = $r53->changeResourceRecordSets("/hostedzone/$ZoneID", $changes);
}
}
$this->_checkStatus(0, $result);
break;
case 'custom':
case 'custom-v6':
if ($this->_dnsVerboseLog)
log_error("Custom dynamic DNS ({$this->_dnsHost}): DNS update() starting.");
if ($this->_dnsUser != '') {
if ($this->_curlIpresolveV4)
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 );
if ($this->_curlSslVerifypeer)
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
else
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
curl_setopt($ch, CURLOPT_USERPWD, "{$this->_dnsUser}:{$this->_dnsPass}");
}
$server = str_replace("%IP%", $this->_dnsIP, $this->_dnsUpdateURL);
if ($this->_dnsVerboseLog)
log_error("Sending request to: ".$server);
curl_setopt($ch, CURLOPT_URL, $server);
break;
case 'cloudflare':
$dnsServer ='api.cloudflare.com';
$dnsHost = str_replace(' ','', $this->_dnsHost);
$host_names = explode('.', $dnsHost);
$bottom_host_name = $host_names[count($host_names) - 2] . '.' . $host_names[count($host_names) - 1];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array(
'X-Auth-Email: '.$this->_dnsUser.'',
'X-Auth-Key: '.$this->_dnsPass.'',
'Content-Type: application/json'
));
// Get zone ID
$getZoneId = "https://{$dnsServer}/client/v4/zones/?name={$bottom_host_name}";
curl_setopt($ch, CURLOPT_URL, $getZoneId);
$output = json_decode(curl_exec($ch));
$zone = $output->result[0]->id;
if ($zone){ // If zone ID was found get host ID
$getHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records?name={$this->_dnsHost}";
curl_setopt($ch, CURLOPT_URL, $getHostId);
$output = json_decode(curl_exec($ch));
$host = $output->result[0]->id;
if ($host){ // If host ID was found update host
$hostData = array(
"content" => "{$this->_dnsIP}",
"type" => "A",
"name" => "{$this->_dnsHost}",
"proxiable" => false,
"proxied" => false
);
$data_json = json_encode($hostData);
$updateHostId = "https://{$dnsServer}/client/v4/zones/{$zone}/dns_records/{$host}";
curl_setopt($ch, CURLOPT_URL, $updateHostId);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json);
}
}
break;
case 'eurodns':
if ($this->_dnsVerboseLog)
log_error("EuroDNS ({$this->_dnsHost}) DNS update() starting.");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://eurodyndns.org/update/";
$port = "";
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
break;
case 'gratisdns':
if ($this->_dnsVerboseLog)
log_error("GratisDNS.dk ({$this->_dnsHost}): DNS update() starting.");
$server = "https://ssl.gratisdns.dk/ddns.phtml";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
list($hostname, $domain) = explode(".", $this->_dnsHost, 2);
curl_setopt($ch, CURLOPT_URL, $server . '?u=' . $this->_dnsUser . '&p=' . $this->_dnsPass . '&h=' . $this->_dnsHost . '&d=' . $domain);
break;
case 'ovh-dynhost':
if ($this->_dnsVerboseLog)
log_error("OVH DynHOST: ({$this->_dnsHost}) DNS update() starting.");
if (isset($this->_dnsWildcard) && $this->_dnsWildcard != "OFF") $this->_dnsWildcard = "ON";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = "https://www.ovh.com/nic/update";
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port . '?system=dyndns&hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP . '&wildcard='.$this->_dnsWildcard . '&mx=' . $this->_dnsMX . '&backmx=NO');
break;
case 'citynetwork':
if ($this->_dnsVerboseLog)
log_error("City Network: ({$this->_dnsHost}) DNS update() starting.");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
$server = 'https://dyndns.citynetwork.se/nic/update';
$port = "";
if($this->_dnsServer)
$server = $this->_dnsServer;
if($this->_dnsPort)
$port = ":" . $this->_dnsPort;
curl_setopt($ch, CURLOPT_URL, $server .$port . '?hostname=' . $this->_dnsHost . '&myip=' . $this->_dnsIP);
break;
case 'duckdns':
if ($this->_dnsVerboseLog)
log_error("Duck DNS ({$this->_dnsHost}): DNS update() starting.");
$server = "https://www.duckdns.org/update";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_URL, $server . '?domains=' . str_replace('.duckdns.org', '', $this->_dnsHost) . '&token=' . $this->_dnsUser);
break;
case 'googledomains':
if ($this->_dnsVerboseLog)
log_error("Google Domains: ({$this->_dnsHost}): DNS update() starting.");
$server = "https://domains.google.com/nic/update";
$post_data['hostname'] = $this->_dnsHost;
$post_data['myip'] = $this->_dnsIP;
$post_data['offline'] = 'no';
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
curl_setopt($ch, CURLOPT_URL, $server);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
break;
case 'strato':
if ($this->_dnsVerboseLog)
log_error("STRATO: ({$this->_dnsHost}): DNS update() starting.");
$server = "https://dyndns.strato.com/nic/update?hostname={$this->_dnsHost}&myip={$this->_dnsIP}";
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_URL, $server);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
break;
case '3322':
if ($this->_dnsVerboseLog)
log_error("3322: ({$this->_dnsHost}): DNS update() starting.");
$server = "http://members.3322.net/dyndns/update?hostname={$this->_dnsHost}&myip={$this->_dnsIP}";
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_URL, $server);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
break;
case 'oray':
if ($this->_dnsVerboseLog)
log_error("Oray: ({$this->_dnsHost}): DNS update() starting.");
$server = "http://ddns.oray.com/ph/update?hostname={$this->_dnsHost}&myip={$this->_dnsIP}";
curl_setopt($ch, CURLOPT_USERPWD, $this->_dnsUser.':'.$this->_dnsPass);
curl_setopt($ch, CURLOPT_URL, $server);
curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
break;
default:
break;
}
if ($this->_dnsService != 'ods' and $this->_dnsService != 'route53') {
$data = curl_exec($ch);
$this->_checkStatus($ch, $data);
@curl_close($ch);
}
}
/*
* Private Function (added 12 July 2005) [beta]
* Retrieve Update Status
*/
function _checkStatus($ch, $data) {
if ($this->_dnsVerboseLog) {
log_error("Dynamic DNS ({$this->_dnsHost}): _checkStatus() starting.");
log_error("Dynamic DNS ({$this->_dnsHost}): Current Service: {$this->_dnsService}");
}
$successful_update = false;
if ($this->_dnsService != 'ods' and $this->_dnsService != 'route53' && @curl_error($ch)) {
$status = "Curl error occurred: " . curl_error($ch);
log_error($status);
$this->status = $status;
return;
}
switch ($this->_dnsService) {
case 'dhs':
break;
case 'noip':
case 'noip-free':
list($ip,$code) = explode(":",$data);
switch ($code) {
case 0:
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP address is current, no update performed.";
$successful_update = true;
break;
case 1:
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) DNS hostname update successful.";
$successful_update = true;
break;
case 2:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Hostname supplied does not exist.";
break;
case 3:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Invalid Username.";
break;
case 4:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Invalid Password.";
break;
case 5:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) To many updates sent.";
break;
case 6:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Account disabled due to violation of No-IP terms of service.";
break;
case 7:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Invalid IP. IP Address submitted is improperly formatted or is a private IP address or is on a blacklist.";
break;
case 8:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Disabled / Locked Hostname.";
break;
case 9:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Host updated is configured as a web redirect and no update was performed.";
break;
case 10:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Group supplied does not exist.";
break;
case 11:
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) DNS group update is successful.";
$successful_update = true;
break;
case 12:
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) DNS group is current, no update performed.";
$successful_update = true;
break;
case 13:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Update client support not available for supplied hostname or group.";
break;
case 14:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Hostname supplied does not have offline settings configured.";
break;
case 99:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
break;
case 100:
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Client disabled. Client should exit and not perform any more updates without user intervention.";
break;
default:
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
$this->_debug("Unknown Response: ".$data);
break;
}
break;
case 'easydns':
if (preg_match('/NOACCESS/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Authentication Failed: Username and/or Password was Incorrect.";
} else if (preg_match('/NOSERVICE/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) No Service: Dynamic DNS Service has been disabled for this domain.";
} else if (preg_match('/ILLEGAL INPUT/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Illegal Input: Self-Explanatory";
} else if (preg_match('/TOOSOON/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Too Soon: Not Enough Time Has Elapsed Since Last Update";
} else if (preg_match('/NOERROR/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'hn':
/* FIXME: add checks */
break;
case 'zoneedit':
if (preg_match('/799/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error 799) Update Failed!";
} else if (preg_match('/700/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error 700) Update Failed!";
} else if (preg_match('/200/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Updated Successfully!";
$successful_update = true;
} else if (preg_match('/201/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'dyns':
if (preg_match("/400/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Bad Request - The URL was malformed. Required parameters were not provided.";
} else if (preg_match('/402/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Update Too Soon - You have tried updating to quickly since last change.";
} else if (preg_match('/403/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Database Error - There was a server-sided database error.";
} else if (preg_match('/405/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Hostname Error - The hostname (".$this->_dnsHost.") doesn't belong to you.";
} else if (preg_match('/200/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'ods':
if (preg_match("/299/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'freedns':
if (preg_match("/has not changed./i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) No Change In IP Address";
$successful_update = true;
} else if (preg_match("/Updated/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Changed Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'dnsexit':
if (preg_match("/is the same/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) No Change In IP Address";
$successful_update = true;
} else if (preg_match("/Success/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Changed Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'staticcling':
if (preg_match("/invalid ip/i", $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Bad Request - The IP provided was invalid.";
} else if (preg_match('/required info missing/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Bad Request - Required parameters were not provided.";
} else if (preg_match('/invalid characters/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Bad Request - Illegal characters in either the username or the password.";
} else if (preg_match('/bad password/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Invalid password.";
} else if (preg_match('/account locked/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) This account has been administratively locked.";
} else if (preg_match('/update too frequent/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Updating too frequently.";
} else if (preg_match('/DB error/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Error) Server side error.";
} else if (preg_match('/success/i', $data)) {
$status = "Dynamic DNS ({$this->_dnsHost}): (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS ({$this->_dnsHost}): (Unknown Response)";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'namecheap':
$tmp = str_replace("^M", "", $data);
$ncresponse = @xml2array($tmp);
if (preg_match("/internal server error/i", $data)) {
$status = "Dynamic DNS: (Error) Server side error.";
} else if (preg_match("/request is badly formed/i", $data)) {
$status = "Dynamic DNS: (Error) Badly Formed Request (check your settings).";
} else if ($ncresponse['interface-response']['ErrCount'] === "0") {
$status = "Dynamic DNS: (Success) IP Address Updated Successfully!";
$successful_update = true;
} else if (is_numeric($ncresponse['interface-response']['ErrCount']) && ($ncresponse['interface-response']['ErrCount'] > 0)) {
$status = "Dynamic DNS: (Error) " . implode(", ", $ncresponse["interface-response"]["errors"]);
$successful_update = true;
} else {
$status = "Dynamic DNS: (Unknown Response)";
log_error("Dynamic DNS: PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'he-net-tunnelbroker':
/*
-ERROR: Missing parameter(s).
-ERROR: Invalid API key or password
-ERROR: Tunnel not found
-ERROR: Another tunnel exists for this IP.
-ERROR: This tunnel is already associated with this IP address
+OK: Tunnel endpoint updated to: x.x.x.x
*/
if (preg_match("/Missing parameter/i", $data)) {
$status = "Dynamic DNS: (Error) Bad Request - Missing/Invalid Parameters.";
} else if (preg_match('/Tunnel not found/i', $data)) {
$status = "Dynamic DNS: (Error) Bad Request - Invalid Tunnel ID.";
} else if (preg_match('/Invalid API key or password/i', $data)) {
$status = "Dynamic DNS: (Error) Invalid username or password.";
} else if (preg_match('/OK:/i', $data)) {
$status = "Dynamic DNS: (Success) IP Address Updated Successfully!";
$successful_update = true;
} else if (preg_match('/This tunnel is already associated with this IP address/i', $data)) {
$status = "Dynamic DNS: (Success) No Change In IP Address.";
$successful_update = true;
} else {
$status = "Dynamic DNS: (Unknown Response)";
log_error("Dynamic DNS: PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'route53':
$successful_update = true;
break;
case 'custom':
case 'custom-v6':
$successful_update = false;
if ($this->_dnsResultMatch == "") {
$successful_update = true;
}else {
$this->_dnsResultMatch = str_replace("%IP%", $this->_dnsIP, $this->_dnsResultMatch);
$matches = preg_split("/(?<!\\\\)\\|/", $this->_dnsResultMatch);
foreach($matches as $match) {
$match= str_replace("\\|", "|", $match);
if(strcmp($match, trim($data, "\t\n\r")) == 0)
$successful_update = true;
}
unset ($matches);
}
if ($successful_update == true)
$status = "Dynamic DNS: (Success) IP Address Updated Successfully!";
else
$status = "Dynamic DNS: (Error) Result did not match.";
break;
case 'cloudflare':
$output = json_decode($data);
if ($output->result->content === $this->_dnsIP){
$status = "Dynamic DNS: (Success) {$this->_dnsHost} updated to {$this->_dnsIP}";
$successful_update = true;
}
elseif ($output->errors[0]->code === 9103){
$status = "Dynamic DNS ({$this->_dnsHost}): ERROR - Invalid Credentials! Don't forget to use API Key for password field with CloudFlare.";
}
elseif (($output->success) && (!$output->result[0]->id)) {
$status = "Dynamic DNS ({$this->_dnsHost}): ERROR - Zone or Host ID was not found, check your hostname.";
}
else {
$status = "Dynamic DNS ({$this->_dnsHost}): UNKNOWN ERROR - {$output->errors[0]->message}";
log_error("Dynamic DNS ({$this->_dnsHost}): PAYLOAD: {$data}");
}
break;
case 'gratisdns':
if (preg_match('/Forkerte værdier/i', $data)) {
$status = "Dynamic DNS: (Error) Wrong values - Update could not be completed.";
} else if (preg_match('/Bruger login: Bruger eksistere ikke/i', $data)) {
$status = "Dynamic DNS: (Error) Unknown username - User does not exist.";
} else if (preg_match('/Bruger login: 1Fejl i kodeord/i', $data)) {
$status = "Dynamic DNS: (Error) Wrong password - Remember password is case sensitive.";
} else if (preg_match('/Domæne kan IKKE administreres af bruger/i', $data)) {
$status = "Dynamic DNS: (Error) User unable to administer the selected domain.";
} else if (preg_match('/OK/i', $data)) {
$status = "Dynamic DNS: (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS: (Unknown Response)";
log_error("Dynamic DNS: PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case 'duckdns':
if (preg_match('/OK/i', $data)) {
$status = "Dynamic DNS: (Success) IP Address Updated Successfully!";
$successful_update = true;
} else {
$status = "Dynamic DNS: (Unknown Response)";
log_error("Dynamic DNS: PAYLOAD: {$data}");
$this->_debug($data);
}
break;
case '3322':
case 'citynetwork':
case 'dnsomatic':
case 'dyndns':
case 'dyndns-custom':
case 'dyndns-static':
case 'eurodns':
case 'googledomains':
case 'he-net':
case 'he-net-v6':
case 'loopia':
case 'opendns':
case 'oray':
case 'ovh-dynhost':
case 'selfhost':
case 'strato':
if (preg_match('/notfqdn/i', $data)) {
$status = "Dynamic DNS: (Error) Not a FQDN";
} elseif (preg_match('/nochg/i', $data)) {
$status = "Dynamic DNS: (Success) No change in IP address";
$successful_update = true;
} elseif (preg_match('/good/i', $data)) {
$status = "Dynamic DNS: (Success) IP address updated successfully ({$this->_dnsIP})";
$successful_update = true;
} elseif (preg_match('/badauth/i', $data)) {
$status = "Dynamic DNS: (Error) Authentication failed";
} elseif (preg_match("/badip/i", $data)) {
$status = "Dynamic DNS: (Error) IP address provided is invalid";
} elseif (preg_match('/nohost/i', $data)) {
$status = "Dynamic DNS: (Error) Hostname does not exist or does not have dynamic DNS enabled";
} elseif (preg_match('/numhost/i', $data)) {
$status = "Dynamic DNS: (Error) You may update up to 20 hosts only";
} elseif (preg_match('/dnserr/i', $data)) {
$status = "Dynamic DNS: (Error) DNS error, stop updating for 30 minutes.";
} elseif (preg_match('/badagent/i', $data)) {
$status = "Dynamic DNS: (Error) Bad request";
} elseif (preg_match('/abuse/i', $data)) {
$status = "Dynamic DNS: (Error) Access has been blocked for abuse";
} elseif (preg_match('/911/i', $data)) {
$status = "Dynamic DNS: (Error) Server-side error or maintenance";
} elseif (preg_match('/yours/i', $data)) {
$status = "Dynamic DNS: (Error) Specified hostname does not exist under this username";
} else {
$status = "Dynamic DNS: (Unknown Response)";
log_error("Dynamic DNS: PAYLOAD: {$data}");
$this->_debug($data);
}
break;
}
if($successful_update == true) {
/* Write WAN IP to cache file */
$wan_ip = $this->_checkIP();
if ($this->_useIPv6 == false && $wan_ip > 0) {
$currentTime = time();
notify_all_remote(sprintf(gettext("Dynamic DNS updated IP Address on %s (%s) to %s"), convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
log_error("Dynamic DNS: updating cache file {$this->_cacheFile}: {$wan_ip}");
@file_put_contents($this->_cacheFile, "{$wan_ip}|{$currentTime}");
} else
@unlink($this->_cacheFile);
if ($this->_useIPv6 == true && $wan_ip > 0) {
$currentTime = time();
notify_all_remote(sprintf(gettext("Dynamic DNS updated IPv6 Address on %s (%s) to %s"), convert_real_interface_to_friendly_descr($this->_if), $this->_if, $wan_ip));
log_error("Dynamic DNS: updating cache file {$this->_cacheFile_v6}: {$wan_ip}");
@file_put_contents($this->_cacheFile_v6, "{$wan_ip}|{$currentTime}");
} else
@unlink($this->_cacheFile_v6);
}
$this->status = $status;
log_error($status);
}
/*
* Private Function (added 12 July 05) [beta]
* Return Error, Set Last Error, and Die.
*/
function _error($errorNumber = '1') {
switch ($errorNumber) {
case 0:
break;
case 2:
$error = 'Dynamic DNS: (ERROR!) No Dynamic DNS Service provider was selected.';
break;
case 3:
$error = 'Dynamic DNS: (ERROR!) No Username Provided.';
break;
case 4:
$error = 'Dynamic DNS: (ERROR!) No Password Provided.';
break;
case 5:
$error = 'Dynamic DNS: (ERROR!) No Hostname Provided.';
break;
case 6:
$error = 'Dynamic DNS: (ERROR!) The Dynamic DNS Service provided is not yet supported.';
break;
case 7:
$error = 'Dynamic DNS: (ERROR!) No Update URL Provided.';
break;
case 8:
$status = "Route 53: (Error) Invalid ZoneID";
break;
case 9:
$status = "Route 53: (Error) Invalid TTL";
break;
case 10:
$error = "Dynamic DNS ({$this->_dnsHost}): No change in my IP address and/or " . $this->_dnsMaxCacheAgeDays . " days has not passed. Not updating dynamic DNS entry.";
break;
default:
$error = "Dynamic DNS: (ERROR!) Unknown Response.";
/* FIXME: $data isn't in scope here */
/* $this->_debug($data); */
break;
}
$this->lastError = $error;
log_error($error);
}
/*
* Private Function (added 12 July 05) [beta]
* - Detect whether or not IP needs to be updated.
* | Written Specifically for pfSense (https://www.pfsense.org) may
* | work with other systems. pfSense base is FreeBSD.
*/
function _detectChange() {
$currentTime = time();
$wan_ip = $this->_checkIP();
if ($wan_ip == 0) {
log_error("Dynamic DNS ({$this->_dnsHost}): Current WAN IP could not be determined, skipping update process.");
return false;
}
$log_error = "Dynamic DNS ({$this->_dnsHost}): Current WAN IP: {$wan_ip} ";
if ($this->_useIPv6 == true) {
if (file_exists($this->_cacheFile_v6)) {
$contents = file_get_contents($this->_cacheFile_v6);
list($cacheIP,$cacheTime) = explode('|', $contents);
$this->_debug($cacheIP.'/'.$cacheTime);
$initial = false;
$log_error .= "Cached IPv6: {$cacheIP} ";
} else {
$cacheIP = '::';
@file_put_contents($this->_cacheFile, "::|{$currentTime}");
$cacheTime = $currentTime;
$initial = true;
$log_error .= "No Cached IPv6 found.";
}
} else {
if (file_exists($this->_cacheFile)) {
$contents = file_get_contents($this->_cacheFile);
list($cacheIP,$cacheTime) = explode('|', $contents);
$this->_debug($cacheIP.'/'.$cacheTime);
$initial = false;
$log_error .= "Cached IP: {$cacheIP} ";
} else {
$cacheIP = '0.0.0.0';
@file_put_contents($this->_cacheFile, "0.0.0.0|{$currentTime}");
$cacheTime = $currentTime;
$initial = true;
$log_error .= "No Cached IP found.";
}
}
if ($this->_dnsVerboseLog)
log_error($log_error);
// Convert seconds = days * hr/day * min/hr * sec/min
$maxCacheAgeSecs = $this->_dnsMaxCacheAgeDays * 24 * 60 * 60;
$needs_updating = FALSE;
/* lets determine if the item needs updating */
if ($cacheIP != $wan_ip) {
$needs_updating = true;
$update_reason = "Dynamic DNS: cacheIP != wan_ip. Updating. ";
$update_reason .= "Cached IP: {$cacheIP} WAN IP: {$wan_ip} ";
}
if (($currentTime - $cacheTime) > $maxCacheAgeSecs) {
$needs_updating = true;
$this->_forceUpdateNeeded = true;
$update_reason = "Dynamic DNS: More than " . $this->_dnsMaxCacheAgeDays . " days. Updating. ";
$update_reason .= "{$currentTime} - {$cacheTime} > {$maxCacheAgeSecs} ";
}
if ($initial == true) {
$needs_updating = true;
$update_reason .= "Initial update. ";
}
/* finally if we need updating then store the
* new cache value and return true
*/
if ($needs_updating == true) {
if ($this->_dnsVerboseLog)
log_error("Dynamic DNS ({$this->_dnsHost}): {$update_reason}");
return true;
}
return false;
}
/*
* Private Function (added 16 July 05) [beta]
* - Writes debug information to a file.
* - This function is only called when a unknown response
* - status is returned from a dynamic DNS service provider.
*/
function _debug($data) {
$string = date('m-d-y h:i:s').' - ('.$this->_debugID.') - ['.$this->_dnsService.'] - '.$data."\n";
$file = fopen($this->_debugFile, 'a');
fwrite($file, $string);
fclose($file);
}
function _checkIP() {
$ip_address = get_dyndns_ip($this->_if, $this->_useIPv6 ? 6 : 4);
if (!is_ipaddr($ip_address)) {
if ($this->_dnsVerboseLog) {
log_error("Dynamic DNS ({$this->_dnsHost}): IP address could not be extracted");
}
$ip_address = 0;
} else {
if ($this->_dnsVerboseLog) {
log_error("Dynamic DNS ({$this->_dnsHost}): {$ip_address} extracted");
}
$this->_dnsIP = $ip_address;
}
return $ip_address;
}
}
<?php
/**
*
* Copyright (c) 2011, Dan Myers.
* Parts copyright (c) 2008, Donovan Schonknecht.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* This is a modified BSD license (the third clause has been removed).
* The BSD license may be found here:
* http://www.opensource.org/licenses/bsd-license.php
*
* Amazon Route 53 is a trademark of Amazon.com, Inc. or its affiliates.
*
* Route53 is based on Donovan Schonknecht's Amazon S3 PHP class, found here:
* http://undesigned.org.za/2007/10/22/amazon-s3-php-class
*
*/
/**
* Amazon Route53 PHP class
*
* @link http://sourceforge.net/projects/php-r53/
* version 0.9.0
*
*/
class Route53
{
const API_VERSION = '2010-10-01';
protected $__accessKey; // AWS Access key
protected $__secretKey; // AWS Secret key
protected $__host;
public function getAccessKey() { return $this->__accessKey; }
public function getSecretKey() { return $this->__secretKey; }
public function getHost() { return $this->__host; }
protected $__verifyHost = 1;
protected $__verifyPeer = 1;
// verifyHost and verifyPeer determine whether curl verifies ssl certificates.
// It may be necessary to disable these checks on certain systems.
// These only have an effect if SSL is enabled.
public function verifyHost() { return $this->__verifyHost; }
public function enableVerifyHost($enable = true) { $this->__verifyHost = $enable; }
public function verifyPeer() { return $this->__verifyPeer; }
public function enableVerifyPeer($enable = true) { $this->__verifyPeer = $enable; }
/**
* Constructor
*
* @param string $accessKey Access key
* @param string $secretKey Secret key
* @return void
*/
public function __construct($accessKey = null, $secretKey = null, $host = 'route53.amazonaws.com') {
if ($accessKey !== null && $secretKey !== null) {
$this->setAuth($accessKey, $secretKey);
}
$this->__host = $host;
}
/**
* Set AWS access key and secret key
*
* @param string $accessKey Access key
* @param string $secretKey Secret key
* @return void
*/
public function setAuth($accessKey, $secretKey) {
$this->__accessKey = $accessKey;
$this->__secretKey = $secretKey;
}
/**
* Lists the hosted zones on the account
*
* @param string marker A pagination marker returned by a previous truncated call
* @param int maxItems The maximum number of items per page. The service uses min($maxItems, 100).
* @return A list of hosted zones
*/
public function listHostedZones($marker = null, $maxItems = 100) {
$rest = new Route53Request($this, 'hostedzone', 'GET');
if($marker !== null) {
$rest->setParameter('marker', $marker);
}
if($maxItems !== 100) {
$rest->setParameter('maxitems', $maxItems);
}
$rest = $rest->getResponse();
if($rest->error === false && $rest->code !== 200) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('listHostedZones', $rest->error);
return false;
}
$response = array();
if (!isset($rest->body))
{
return $response;
}
$zones = array();
foreach($rest->body->HostedZones->HostedZone as $z)
{
$zones[] = $this->parseHostedZone($z);
}
$response['HostedZone'] = $zones;
if(isset($rest->body->MaxItems)) {
$response['MaxItems'] = (string)$rest->body->MaxItems;
}
if(isset($rest->body->IsTruncated)) {
$response['IsTruncated'] = (string)$rest->body->IsTruncated;
if($response['IsTruncated'] == 'true') {
$response['NextMarker'] = (string)$rest->body->NextMarker;
}
}
return $response;
}
/**
* Retrieves information on a specified hosted zone
*
* @param string zoneId The id of the hosted zone, as returned by CreateHostedZoneResponse or ListHostedZoneResponse
* In other words, if ListHostedZoneResponse shows the zone's Id as '/hostedzone/Z1PA6795UKMFR9',
* then that full value should be passed here, including the '/hostedzone/' prefix.
* @return A data structure containing information about the specified zone
*/
public function getHostedZone($zoneId) {
// we'll strip off the leading forward slash, so we can use it as the action directly.
$zoneId = trim($zoneId, '/');
$rest = new Route53Request($this, $zoneId, 'GET');
$rest = $rest->getResponse();
if($rest->error === false && $rest->code !== 200) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('getHostedZone', $rest->error);
return false;
}
$response = array();
if (!isset($rest->body))
{
return $response;
}
$response['HostedZone'] = $this->parseHostedZone($rest->body->HostedZone);
$response['NameServers'] = $this->parseDelegationSet($rest->body->DelegationSet);
return $response;
}
/**
* Creates a new hosted zone
*
* @param string name The name of the hosted zone (e.g. "example.com.")
* @param string reference A user-specified unique reference for this request
* @param string comment An optional user-specified comment to attach to the zone
* @return A data structure containing information about the newly created zone
*/
public function createHostedZone($name, $reference, $comment = '') {
// hosted zone names must end with a period, but people will forget this a lot...
if(strrpos($name, '.') != (strlen($name) - 1)) {
$name .= '.';
}
$data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$data .= '<CreateHostedZoneRequest xmlns="https://route53.amazonaws.com/doc/'.Route53::API_VERSION."/\">\n";
$data .= '<Name>'.$name."</Name>\n";
$data .= '<CallerReference>'.$reference."</CallerReference>\n";
if(strlen($comment) > 0) {
$data .= "<HostedZoneConfig>\n";
$data .= '<Comment>'.$comment."</Comment>\n";
$data .= "</HostedZoneConfig>\n";
}
$data .= "</CreateHostedZoneRequest>\n";
$rest = new Route53Request($this, 'hostedzone', 'POST', $data);
$rest = $rest->getResponse();
if($rest->error === false && !in_array($rest->code, array(200, 201, 202, 204)) ) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('createHostedZone', $rest->error);
return false;
}
$response = array();
if (!isset($rest->body))
{
return $response;
}
$response['HostedZone'] = $this->parseHostedZone($rest->body->HostedZone);
$response['ChangeInfo'] = $this->parseChangeInfo($rest->body->ChangeInfo);
$response['NameServers'] = $this->parseDelegationSet($rest->body->DelegationSet);
return $response;
}
/**
* Retrieves information on a specified hosted zone
*
* @param string zoneId The id of the hosted zone, as returned by CreateHostedZoneResponse or ListHostedZoneResponse
* In other words, if ListHostedZoneResponse shows the zone's Id as '/hostedzone/Z1PA6795UKMFR9',
* then that full value should be passed here, including the '/hostedzone/' prefix.
* @return The change request data corresponding to this delete
*/
public function deleteHostedZone($zoneId) {
// we'll strip off the leading forward slash, so we can use it as the action directly.
$zoneId = trim($zoneId, '/');
$rest = new Route53Request($this, $zoneId, 'DELETE');
$rest = $rest->getResponse();
if($rest->error === false && $rest->code !== 200) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('deleteHostedZone', $rest->error);
return false;
}
if (!isset($rest->body))
{
return array();
}
return $this->parseChangeInfo($rest->body->ChangeInfo);
}
/**
* Retrieves a list of resource record sets for a given zone
*
* @param string zoneId The id of the hosted zone, as returned by CreateHostedZoneResponse or ListHostedZoneResponse
* In other words, if ListHostedZoneResponse shows the zone's Id as '/hostedzone/Z1PA6795UKMFR9',
* then that full value should be passed here, including the '/hostedzone/' prefix.
* @param string type The type of resource record set to begin listing from. If this is specified, $name must also be specified.
* Must be one of: A, AAAA, CNAME, MX, NS, PTR, SOA, SPF, SRV, TXT
* @param string name The name at which to begin listing resource records (in the lexographic order of records).
* @param int maxItems The maximum number of results to return. The service uses min($maxItems, 100).
* @return The list of matching resource record sets
*/
public function listResourceRecordSets($zoneId, $type = '', $name = '', $maxItems = 100) {
// we'll strip off the leading forward slash, so we can use it as the action directly.
$zoneId = trim($zoneId, '/');
$rest = new Route53Request($this, $zoneId.'/rrset', 'GET');
if(strlen($type) > 0) {
$rest->setParameter('type', $type);
}
if(strlen($name) > 0) {
$rest->setParameter('name', $name);
}
if($maxItems != 100) {
$rest->setParameter('maxitems', $maxItems);
}
$rest = $rest->getResponse();
if($rest->error === false && $rest->code !== 200) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('listResourceRecordSets', $rest->error);
return false;
}
$response = array();
if (!isset($rest->body))
{
return $response;
}
$recordSets = array();
foreach($rest->body->ResourceRecordSets->ResourceRecordSet as $set) {
$recordSets[] = $this->parseResourceRecordSet($set);
}
$response['ResourceRecordSets'] = $recordSets;
if(isset($rest->body->MaxItems)) {
$response['MaxItems'] = (string)$rest->body->MaxItems;
}
if(isset($rest->body->IsTruncated)) {
$response['IsTruncated'] = (string)$rest->body->IsTruncated;
if($response['IsTruncated'] == 'true') {
$response['NextRecordName'] = (string)$rest->body->NextRecordName;
$response['NextRecordType'] = (string)$rest->body->NextRecordType;
}
}
return $response;
}
/**
* Makes the specified resource record set changes (create or delete).
*
* @param string zoneId The id of the hosted zone, as returned by CreateHostedZoneResponse or ListHostedZoneResponse
* In other words, if ListHostedZoneResponse shows the zone's Id as '/hostedzone/Z1PA6795UKMFR9',
* then that full value should be passed here, including the '/hostedzone/' prefix.
* @param array changes An array of change objects, as they are returned by the prepareChange utility method.
* You may also pass a single change object.
* @param string comment An optional comment to attach to the change request
* @return The status of the change request
*/
public function changeResourceRecordSets($zoneId, $changes, $comment = '') {
// we'll strip off the leading forward slash, so we can use it as the action directly.
$zoneId = trim($zoneId, '/');
$data = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
$data .= '<ChangeResourceRecordSetsRequest xmlns="https://route53.amazonaws.com/doc/'.Route53::API_VERSION."/\">\n";
$data .= "<ChangeBatch>\n";
if(strlen($comment) > 0) {
$data .= '<Comment>'.$comment."</Comment>\n";
}
if(!is_array($changes)) {
$changes = array($changes);
}
$data .= "<Changes>\n";
foreach($changes as $change) {
$data .= $change;
}
$data .= "</Changes>\n";
$data .= "</ChangeBatch>\n";
$data .= "</ChangeResourceRecordSetsRequest>\n";
$rest = new Route53Request($this, $zoneId.'/rrset', 'POST', $data);
$rest = $rest->getResponse();
if($rest->error === false && !in_array($rest->code, array(200, 201, 202, 204))) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('changeResourceRecordSets', $rest->error);
return false;
}
if (!isset($rest->body))
{
return array();
}
return $this->parseChangeInfo($rest->body->ChangeInfo);
}
/**
* Retrieves information on a specified change request
*
* @param string changeId The id of the change, as returned by CreateHostedZoneResponse or ChangeResourceRecordSets
* In other words, if CreateHostedZoneResponse showed the change's Id as '/change/C2682N5HXP0BZ4',
* then that full value should be passed here, including the '/change/' prefix.
* @return The status of the change request
*/
public function getChange($changeId) {
// we'll strip off the leading forward slash, so we can use it as the action directly.
$zoneId = trim($changeId, '/');
$rest = new Route53Request($this, $changeId, 'GET');
$rest = $rest->getResponse();
if($rest->error === false && $rest->code !== 200) {
$rest->error = array('code' => $rest->code, 'message' => 'Unexpected HTTP status');
}
if($rest->error !== false) {
$this->__triggerError('getChange', $rest->error);
return false;
}
if (!isset($rest->body))
{
return array();
}
return $this->parseChangeInfo($rest->body->ChangeInfo);
}
/**
* Utility function to parse a HostedZone tag structure
*/
private function parseHostedZone($tag) {
$zone = array();
$zone['Id'] = (string)$tag->Id;
$zone['Name'] = (string)$tag->Name;
$zone['CallerReference'] = (string)$tag->CallerReference;
// these might always be set, but check just in case, since
// their values are option on CreateHostedZone requests
if(isset($tag->Config) && isset($tag->Config->Comment)) {
$zone['Config'] = array('Comment' => (string)$tag->Config->Comment);
}
return $zone;
}
/**
* Utility function to parse a ChangeInfo tag structure
*/
private function parseChangeInfo($tag) {
$info = array();
$info['Id'] = (string)$tag->Id;
$info['Status'] = (string)$tag->Status;
$info['SubmittedAt'] = (string)$tag->SubmittedAt;
return $info;
}
/**
* Utility function to parse a DelegationSet tag structure
*/
private function parseDelegationSet($tag) {
$servers = array();
foreach($tag->NameServers->NameServer as $ns) {
$servers[] = (string)$ns;
}
return $servers;
}
/**
* Utility function to parse a ResourceRecordSet tag structure
*/
private function parseResourceRecordSet($tag) {
$rrs = array();
$rrs['Name'] = (string)$tag->Name;
$rrs['Type'] = (string)$tag->Type;
$rrs['TTL'] = (string)$tag->TTL;
$rrs['ResourceRecords'] = array();
foreach($tag->ResourceRecords->ResourceRecord as $rr) {
$rrs['ResourceRecords'][] = (string)$rr->Value;
}
return $rrs;
}
/**
* Utility function to prepare a Change object for ChangeResourceRecordSets requests.
* All fields are required.
*
* @param string action The action to perform. One of: CREATE, DELETE
* @param string name The name to perform the action on.
* If it does not end with '.', then AWS treats the name as relative to the zone root.
* @param string type The type of record being modified.
* Must be one of: A, AAAA, CNAME, MX, NS, PTR, SOA, SPF, SRV, TXT
* @param int ttl The time-to-live value for this record, in seconds.
* @param array records An array of resource records to attach to this change.
* Each member of this array can either be a string, or an array of strings.
* Passing an array of strings will attach multiple values to a single resource record.
* If a single string is passed as $records instead of an array,
* it will be treated as a single-member array.
* @return object An opaque object containing the change request.
* Do not write code that depends on the contents of this object, as it may change at any time.
*/
public function prepareChange($action, $name, $type, $ttl, $records) {
$change = "<Change>\n";
$change .= '<Action>'.$action."</Action>\n";
$change .= "<ResourceRecordSet>\n";
$change .= '<Name>'.$name."</Name>\n";
$change .= '<Type>'.$type."</Type>\n";
$change .= '<TTL>'.$ttl."</TTL>\n";
$change .= "<ResourceRecords>\n";
if(!is_array($records)) {
$records = array($records);
}
foreach($records as $record) {
$change .= "<ResourceRecord>\n";
if(is_array($record)) {
foreach($record as $value) {
$change .= '<Value>'.$value."</Value>\n";
}
}
else {
$change .= '<Value>'.$record."</Value>\n";
}
$change .= "</ResourceRecord>\n";
}
$change .= "</ResourceRecords>\n";
$change .= "</ResourceRecordSet>\n";
$change .= "</Change>\n";
return $change;
}
/**
* Trigger an error message
*
* @internal Used by member functions to output errors
* @param array $error Array containing error information
* @return string
*/
public function __triggerError($functionname, $error)
{
if($error == false) {
log_error(sprintf("Route53::%s(): Encountered an error, but no description given", $functionname));
}
else if(isset($error['curl']) && $error['curl'])
{
log_error(sprintf("Route53::%s(): %s %s", $functionname, $error['code'], $error['message']));
}
else if(isset($error['Error']))
{
$e = $error['Error'];
$message = sprintf("Route53::%s(): %s - %s: %s\nRequest Id: %s\n", $functionname, $e['Type'], $e['Code'], $e['Message'], $error['RequestId']);
log_error($message);
}
}
/**
* Callback handler for 503 retries.
*
* @internal Used by SimpleDBRequest to call the user-specified callback, if set
* @param $attempt The number of failed attempts so far
* @return The retry delay in microseconds, or 0 to stop retrying.
*/
public function __executeServiceTemporarilyUnavailableRetryDelay($attempt)
{
if(is_callable($this->__serviceUnavailableRetryDelayCallback)) {
$callback = $this->__serviceUnavailableRetryDelayCallback;
return $callback($attempt);
}
return 0;
}
}
final class Route53Request
{
private $r53, $action, $verb, $data, $parameters = array();
public $response;
/**
* Constructor
*
* @param string $r53 The Route53 object making this request
* @param string $action SimpleDB action
* @param string $verb HTTP verb
* @param string $data For POST requests, the data being posted (optional)
* @return mixed
*/
function __construct($r53, $action, $verb, $data = '') {
$this->r53 = $r53;
$this->action = $action;
$this->verb = $verb;
$this->data = $data;
$this->response = new STDClass;
$this->response->error = false;
}
/**
* Set request parameter
*
* @param string $key Key
* @param string $value Value
* @param boolean $replace Whether to replace the key if it already exists (default true)
* @return void
*/
public function setParameter($key, $value, $replace = true) {
if(!$replace && isset($this->parameters[$key]))
{
$temp = (array)($this->parameters[$key]);
$temp[] = $value;
$this->parameters[$key] = $temp;
}
else
{
$this->parameters[$key] = $value;
}
}
/**
* Get the response
*
* @return object | false
*/
public function getResponse() {
$params = array();
foreach ($this->parameters as $var => $value)
{
if(is_array($value))
{
foreach($value as $v)
{
$params[] = $var.'='.$this->__customUrlEncode($v);
}
}
else
{
$params[] = $var.'='.$this->__customUrlEncode($value);
}
}
sort($params, SORT_STRING);
$query = implode('&', $params);
// must be in format 'Sun, 06 Nov 1994 08:49:37 GMT'
$date = gmdate('D, d M Y H:i:s e');
$headers = array();
$headers[] = 'Date: '.$date;
$headers[] = 'Host: '.$this->r53->getHost();
$auth = 'AWS3-HTTPS AWSAccessKeyId='.$this->r53->getAccessKey();
$auth .= ',Algorithm=HmacSHA256,Signature='.$this->__getSignature($date);
$headers[] = 'X-Amzn-Authorization: '.$auth;
$url = 'https://'.$this->r53->getHost().'/'.Route53::API_VERSION.'/'.$this->action.'?'.$query;
// Basic setup
$curl = curl_init();
curl_setopt($curl, CURLOPT_USERAGENT, 'Route53/php');
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, ($this->r53->verifyHost() ? 1 : 0));
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, ($this->r53->verifyPeer() ? 1 : 0));
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, false);
curl_setopt($curl, CURLOPT_WRITEFUNCTION, array(&$this, '__responseWriteCallback'));
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
// Request types
switch ($this->verb) {
case 'GET': break;
case 'POST':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $this->verb);
if(strlen($this->data) > 0) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->data);
$headers[] = 'Content-Type: text/plain';
$headers[] = 'Content-Length: '.strlen($this->data);
}
break;
case 'DELETE':
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE');
break;
default: break;
}
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
curl_setopt($curl, CURLOPT_HEADER, false);
// Execute, grab errors
if (curl_exec($curl)) {
$this->response->code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
} else {
$this->response->error = array(
'curl' => true,
'code' => curl_errno($curl),
'message' => curl_error($curl),
'resource' => $this->resource
);
}
@curl_close($curl);
// Parse body into XML
if ($this->response->error === false && isset($this->response->body)) {
$this->response->body = simplexml_load_string($this->response->body);
// Grab Route53 errors
if (!in_array($this->response->code, array(200, 201, 202, 204))
&& isset($this->response->body->Error)) {
$error = $this->response->body->Error;
$output = array();
$output['curl'] = false;
$output['Error'] = array();
$output['Error']['Type'] = (string)$error->Type;
$output['Error']['Code'] = (string)$error->Code;
$output['Error']['Message'] = (string)$error->Message;
$output['RequestId'] = (string)$this->response->body->RequestId;
$this->response->error = $output;
unset($this->response->body);
}
}
return $this->response;
}
/**
* CURL write callback
*
* @param resource &$curl CURL resource
* @param string &$data Data
* @return integer
*/
private function __responseWriteCallback(&$curl, &$data) {
$this->response->body .= $data;
return strlen($data);
}
/**
* Contributed by afx114
* URL encode the parameters as per http://docs.amazonwebservices.com/AWSECommerceService/latest/DG/index.html?Query_QueryAuth.html
* PHP's rawurlencode() follows RFC 1738, not RFC 3986 as required by Amazon. The only difference is the tilde (~), so convert it back after rawurlencode
* See: http://www.morganney.com/blog/API/AWS-Product-Advertising-API-Requires-a-Signed-Request.php
*
* @param string $var String to encode
* @return string
*/
private function __customUrlEncode($var) {
return str_replace('%7E', '~', rawurlencode($var));
}
/**
* Generate the auth string using Hmac-SHA256
*
* @internal Used by SimpleDBRequest::getResponse()
* @param string $string String to sign
* @return string
*/
private function __getSignature($string) {
return base64_encode(hash_hmac('sha256', $string, $this->r53->getSecretKey(), true));
}
}
......@@ -44,7 +44,6 @@
* targets in the future:
*/
require_once('plugins.inc.d/dnsmasq.inc');
require_once('plugins.inc.d/dyndns.inc');
require_once('plugins.inc.d/ipsec.inc');
require_once('plugins.inc.d/openvpn.inc');
require_once('plugins.inc.d/openssh.inc');
......
#!/usr/local/bin/php
<?php
/*
Copyright (C) 2004 Scott Ullrich
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once("config.inc");
require_once("interfaces.inc");
require_once("util.inc");
require_once("filter.inc");
require_once("services.inc");
require_once("plugins.inc.d/dyndns.inc");
if (isset($argv[1])) {
$argument = trim($argv[1], " \n");
} else {
$argument = null;
}
if (empty($argument)) {
dyndns_configure_do(true);
} else {
$interface = lookup_gateway_interface_by_name($argument);
if (empty($interface)) {
$interface = $argument;
}
dyndns_configure_do(true, $interface);
}
<acl>
<page-services-dynamicdnsclients>
<name>Services: Dynamic DNS clients</name>
<patterns>
<pattern>services_dyndns.php*</pattern>
<pattern>services_dyndns_edit.php*</pattern>
</patterns>
</page-services-dynamicdnsclients>
</acl>
<menu>
<Services>
<DynamicDNS VisibleName="Dynamic DNS" url="/services_dyndns.php" cssClass="fa fa-tags fa-fw">
<Edit url="/services_dyndns_edit.php*" visibility="hidden"/>
</DynamicDNS>
</Services>
</menu>
[reload]
command:/usr/local/etc/rc.dyndns
description:Dynamic DNS Update
parameters:%s
type:script
message:updating dyndns %s
<?php
/*
Copyright (C) 2014-2016 Deciso B.V.
Copyright (C) 2008 Ermal Luçi
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
require_once("interfaces.inc");
require_once("services.inc");
require_once("system.inc");
require_once("plugins.inc.d/dyndns.inc");
if (empty($config['dyndnses']['dyndns']) || !isset($config['dyndnses']['dyndns'])) {
$config['dyndnses']['dyndns'] = array();
}
$a_dyndns = &$config['dyndnses']['dyndns'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['act']) && $_POST['act'] == "del" && isset($_POST['id'])) {
if (!empty($a_dyndns[$_POST['id']])) {
$conf = $a_dyndns[$_POST['id']];
@unlink(dyndns_cache_file($conf, 4));
@unlink(dyndns_cache_file($conf, 6));
unset($a_dyndns[$_POST['id']]);
write_config();
system_cron_configure();
}
exit;
} elseif (isset($_POST['act']) && $_POST['act'] == "toggle" && isset($_POST['id'])) {
if (!empty($a_dyndns[$_POST['id']])) {
if (!empty($a_dyndns[$_POST['id']]['enable'])) {
$a_dyndns[$_POST['id']]['enable'] = false;
} else {
$a_dyndns[$_POST['id']]['enable'] = true;
}
write_config();
system_cron_configure();
if ($a_dyndns[$_POST['id']]['enable']) {
$a_dyndns[$_POST['id']]['force'] = true;
dyndns_configure_client($a_dyndns[$_POST['id']]);
}
}
exit;
}
}
include("head.inc");
legacy_html_escape_form_data($a_dyndns);
$main_buttons = array(
array('label' => gettext('Add'), 'href' => 'services_dyndns_edit.php'),
);
?>
<body>
<script type="text/javascript">
$( document ).ready(function() {
// delete service action
$(".act_delete_service").click(function(event){
event.preventDefault();
var id = $(this).data("id");
BootstrapDialog.show({
type:BootstrapDialog.TYPE_DANGER,
title: "<?= gettext("Dynamic DNS");?>",
message: "<?=gettext("Do you really want to delete this entry?");?>",
buttons: [{
label: "<?= gettext("No");?>",
action: function(dialogRef) {
dialogRef.close();
}}, {
label: "<?= gettext("Yes");?>",
action: function(dialogRef) {
$.post(window.location, {act: 'del', id:id}, function(data) {
location.reload();
});
}
}]
});
});
// link toggle buttons
$(".act_toggle").click(function(event){
event.preventDefault();
$.post(window.location, {act: 'toggle', id:$(this).data("id")}, function(data) {
location.reload();
});
});
// watch scroll position and set to last known on page load
watchScrollPosition();
});
</script>
<?php include("fbegin.inc"); ?>
<section class="page-content-main">
<div class="container-fluid">
<div class="row">
<section class="col-xs-12">
<div class="tab-content content-box col-xs-12">
<form method="post" name="iform" id="iform">
<div class="table-responsive">
<table class="table table-striped">
<thead>
<tr>
<th><?=gettext("Interface");?></th>
<th><?=gettext("Service");?></th>
<th><?=gettext("Hostname");?></th>
<th><?=gettext("Cached IP");?></th>
<th><?=gettext("Description");?></th>
<th></th>
</tr>
</thead>
<tbody>
<?php
$i = 0;
foreach ($a_dyndns as $dyndns): ?>
<tr>
<td>
<a href="#" class="act_toggle" data-id="<?=$i;?>" data-toggle="tooltip" title="<?=(!empty($dyndns['enable'])) ? gettext("disable") : gettext("enable");?>">
<span class="glyphicon glyphicon-play <?=(!empty($dyndns['enable'])) ? "text-success" : "text-muted";?>"></span>
</a>
<?=!empty($config['interfaces'][$dyndns['interface']]['descr']) ? $config['interfaces'][$dyndns['interface']]['descr'] : strtoupper($dyndns['interface']);?>
</td>
<td><?=dyndns_list()[$dyndns['type']];?></td>
<td><?=$dyndns['host'];?></td>
<td>
<?php
$filename = dyndns_cache_file($dyndns, 4);
$fdata = '';
if (file_exists($filename) && !empty($dyndns['enable'])) {
$ipaddr = get_dyndns_ip($dyndns['interface'], 4);
$fdata = @file_get_contents($filename);
}
$filename_v6 = dyndns_cache_file($dyndns, 6);
$fdata6 = '';
if (file_exists($filename_v6) && !empty($dyndns['enable'])) {
$ipv6addr = get_dyndns_ip($dyndns['interface'], 6);
$fdata6 = @file_get_contents($filename_v6);
}
if (!empty($fdata)) {
$cached_ip_s = explode('|', $fdata);
$cached_ip = $cached_ip_s[0];
echo sprintf(
'<font color="%s">%s</font>',
$ipaddr != $cached_ip ? 'red' : 'green',
htmlspecialchars($cached_ip)
);
} elseif (!empty($fdata6)) {
$cached_ipv6_s = explode('|', $fdata6);
$cached_ipv6 = $cached_ipv6_s[0];
echo sprintf(
'<font color="%s">%s</font>',
$ipv6addr != $cached_ipv6 ? 'red' : 'green',
htmlspecialchars($cached_ipv6)
);
} else {
echo sprintf('<span class="text-muted">%s</span>', gettext('N/A'));
}?>
</td>
<td><?=$dyndns['descr'];?></td>
<td>
<a href="services_dyndns_edit.php?id=<?=$i;?>" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pencil"></span></a>
<a href="#" data-id="<?=$i;?>" class="act_delete_service"><button type="button" class="btn btn-xs btn-default"><span class="fa fa-trash text-muted"></span></button></a>
</td>
</tr>
<?php
$i++;
endforeach; ?>
</tbody>
</table>
</div>
</form>
</div>
</section>
</div>
</div>
</section>
<?php include("foot.inc"); ?>
<?php
/*
Copyright (C) 2014-2015 Deciso B.V.
Copyright (C) 2008 Ermal Luçi
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
require_once("services.inc") ;
require_once("interfaces.inc");
require_once("system.inc");
require_once("plugins.inc.d/dyndns.inc");
/* returns true if $uname is a valid dynamic DNS username */
function is_dyndns_username($uname)
{
if (!is_string($uname)) {
return false;
} elseif (preg_match("/[^a-z0-9\-.@_:]/i", $uname)) {
return false;
} else {
return true;
}
}
if (!isset($config['dyndnses']['dyndns'])) {
$config['dyndnses']['dyndns'] = array();
}
$a_dyndns = &$config['dyndnses']['dyndns'];
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
if (isset($_GET['id']) && !empty($a_dyndns[$_GET['id']])) {
$id = $_GET['id'];
}
$config_copy_fieldnames = array('username', 'password', 'host', 'mx', 'type', 'zoneid', 'ttl', 'updateurl',
'resultmatch', 'requestif', 'descr', 'interface');
foreach ($config_copy_fieldnames as $fieldname) {
if (isset($id) && isset($a_dyndns[$id][$fieldname])) {
$pconfig[$fieldname] = $a_dyndns[$id][$fieldname];
} else {
$pconfig[$fieldname] = null;
}
}
if (isset($id)) {
$pconfig['enable'] = isset($a_dyndns[$id]['enable']);
} else {
$pconfig['enable'] = true;
}
$pconfig['wildcard'] = isset($id) && isset($a_dyndns[$id]['wildcard']);
$pconfig['verboselog'] = isset($id) && isset($a_dyndns[$id]['verboselog']);
$pconfig['curl_ipresolve_v4'] = isset($id) && isset($a_dyndns[$id]['curl_ipresolve_v4']);
$pconfig['curl_ssl_verifypeer'] = isset($id) && isset($a_dyndns[$id]['curl_ssl_verifypeer']);
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
if (isset($_POST['id']) && !empty($a_dyndns[$_POST['id']])) {
$id = $_POST['id'];
}
$input_errors = array();
$pconfig = $_POST;
if(($pconfig['type'] == "freedns" || $pconfig['type'] == "namecheap") && $pconfig['username'] == "") {
$pconfig['username'] = "none";
}
/* input validation */
$reqdfields = array();
$reqdfieldsn = array();
$reqdfields = array('type');
$reqdfieldsn = array(gettext('Service type'));
if ($pconfig['type'] != 'custom' && $pconfig['type'] != 'custom-v6') {
$reqdfields[] = 'host';
$reqdfieldsn[] = gettext('Hostname');
$reqdfields[] = 'username';
$reqdfieldsn[] = gettext('Username');
if ($pconfig['type'] != 'duckdns') {
$reqdfields[] = 'password';
$reqdfieldsn[] = gettext('Password');
}
} else {
$reqdfields[] = 'updateurl';
$reqdfieldsn[] = gettext('Update URL');
}
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
if (isset($pconfig['host']) && in_array('host', $reqdfields)) {
/* Namecheap can have a @. in hostname */
if ($pconfig['type'] == "namecheap" && substr($pconfig['host'], 0, 2) == '@.') {
$host_to_check = substr($pconfig['host'], 2);
} else {
$host_to_check = $pconfig['host'];
}
if (!is_domain($host_to_check)) {
$input_errors[] = gettext("The Hostname contains invalid characters.");
}
}
if (!empty($pconfig['mx']) && !is_domain($pconfig['mx'])) {
$input_errors[] = gettext("The MX contains invalid characters.");
}
if ((in_array("username", $reqdfields) && !empty($pconfig['username']) && !is_dyndns_username($pconfig['username'])) || ((in_array("username", $reqdfields)) && ($pconfig['username'] == ""))) {
$input_errors[] = gettext("The username contains invalid characters.");
}
if (count($input_errors) == 0) {
$dyndns = array();
$dyndns['type'] = $pconfig['type'];
$dyndns['username'] = $pconfig['username'];
$dyndns['password'] = $pconfig['password'];
$dyndns['host'] = $pconfig['host'];
$dyndns['mx'] = $pconfig['mx'];
$dyndns['wildcard'] = !empty($pconfig['wildcard']);
$dyndns['verboselog'] = !empty($pconfig['verboselog']);
$dyndns['curl_ipresolve_v4'] = !empty($pconfig['curl_ipresolve_v4']);
$dyndns['curl_ssl_verifypeer'] = !empty($pconfig['curl_ssl_verifypeer']);
$dyndns['enable'] = !empty($pconfig['enable']);
$dyndns['interface'] = $pconfig['interface'];
$dyndns['zoneid'] = $pconfig['zoneid'];
$dyndns['ttl'] = $pconfig['ttl'];
$dyndns['updateurl'] = $pconfig['updateurl'];
// Trim hard-to-type but sometimes returned characters
$dyndns['resultmatch'] = trim($pconfig['resultmatch'], "\t\n\r");
($dyndns['type'] == "custom" || $dyndns['type'] == "custom-v6") ? $dyndns['requestif'] = $pconfig['requestif'] : $dyndns['requestif'] = $pconfig['interface'];
$dyndns['descr'] = $pconfig['descr'];
$dyndns['force'] = isset($pconfig['force']);
if ($dyndns['username'] == "none") {
$dyndns['username'] = "";
}
if (isset($id)) {
$a_dyndns[$id] = $dyndns;
} else {
$a_dyndns[] = $dyndns;
$id = count($a_dyndns) - 1;
}
$dyndns['id'] = $id;
for($i = 0; $i < count($a_dyndns); $i++) {
$a_dyndns[$i]['id'] = $i;
}
write_config();
system_cron_configure();
if ($dyndns['force']) {
dyndns_configure_client($dyndns);
}
header(url_safe('Location: /services_dyndns.php'));
exit;
}
}
legacy_html_escape_form_data($pconfig);
include("head.inc");
?>
<body>
<?php include("fbegin.inc"); ?>
<script type="text/javascript">
$( document ).ready(function() {
$("#type").change(function(){
$(".opt_field").hide();
switch ($(this).val()) {
case "custom":
case "custom-v6":
$(".type_custom").show();
break;
case "route53":
$(".type_route53").show();
break;
default:
$(".type_default").show();
break;
}
$(window).resize(); // force zebra re-stripe (opnsense_standard_table_form)
});
$("#type").change();
});
</script>
<section class="page-content-main">
<div class="container-fluid">
<div class="row">
<?php if (isset($input_errors) && count($input_errors) > 0) print_input_errors($input_errors); ?>
<section class="col-xs-12">
<div class="content-box">
<form method="post" name="iform" id="iform">
<div class="table-responsive">
<table class="table table-striped opnsense_standard_table_form">
<tr>
<td width="22%"><strong><?= gettext("Dynamic DNS client") ?></strong></td>
<td width="78%" align="right">
<small><?= gettext("full help") ?> </small>
<i class="fa fa-toggle-off text-danger" style="cursor: pointer;" id="show_all_help_page" type="button"></i>
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Enable") ?></td>
<td>
<input name="enable" type="checkbox" id="enable" value="<?= gettext("yes") ?>" <?= empty($pconfig['enable']) ? '' : 'checked="checked"' ?> />
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Service type") ?></td>
<td>
<select name="type" class="selectpicker" id="type">
<?php
foreach (dyndns_list() as $value => $type):?>
<option value="<?= $value ?>" <?= $value == $pconfig['type'] ? 'selected="selected"' : '' ?>>
<?= $type ?>
</option>
<?php
endforeach;?>
</select>
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Interface to monitor") ?></td>
<td>
<select name="interface" class="selectpicker" id="interface">
<?php
$iflist = get_configured_interface_with_descr();
$iflist = array_merge($iflist, return_gateway_groups_array());
foreach ($iflist as $if => $ifdesc):?>
<option value="<?= $if ?>" <?=$pconfig['interface'] == $if ? 'selected="selected"' : '';?>>
<?= is_array($ifdesc) ? $if : htmlspecialchars($ifdesc) ?>
</option>
<?php
endforeach;?>
</select>
</td>
</tr>
<tr class="opt_field type_custom">
<td><a id="help_for_requestif" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Interface to send update from") ?></td>
<td>
<select name="requestif" class="selectpicker" id="requestif">
<?php
$iflist = get_configured_interface_with_descr();
$iflist = array_merge($iflist, return_gateway_groups_array());
foreach ($iflist as $if => $ifdesc):?>
<option value="<?= $if ?>" <?= $pconfig['requestif'] == $if ? 'selected="selected"' : '' ?>>
<?= is_array($ifdesc) ? $if : htmlspecialchars($ifdesc) ?>
</option>
<?php
endforeach;?>
</select>
<div class="hidden" for="help_for_requestif">
<?= gettext("Note: This is almost always the same as the Interface to Monitor.");?>
</div>
</td>
</tr>
<tr>
<td><a id="help_for_host" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Hostname") ?></td>
<td>
<input name="host" type="text" id="host" value="<?= $pconfig['host'] ?>" />
<div class="hidden" for="help_for_host">
<?= gettext("Enter the complete host/domain name. example: myhost.dyndns.org") ?><br />
<?= gettext("For he.net tunnelbroker, enter your tunnel ID") ?>
</div>
</td>
</tr>
<tr class="opt_field type_default type_route53">
<td><a id="help_for_mx" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("MX") ?></td>
<td>
<input name="mx" type="text" id="mx" value="<?= $pconfig['mx'] ?>" />
<div class="hidden" for="help_for_mx">
<?= gettext("Note: With a dynamic DNS service you can only use a hostname, not an IP address.") ?>
<br />
<?= gettext("Set this option only if you need a special MX record. Not all services support this.") ?>
</div>
</td>
</tr>
<tr class="opt_field type_default type_route53">
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Wildcards") ?></td>
<td>
<input name="wildcard" type="checkbox" id="wildcard" value="yes" <?= empty($pconfig['wildcard']) ? '' : 'checked="checked"' ?> />
<strong><?= gettext("Enable Wildcard") ?></strong>
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Verbose logging") ?></td>
<td>
<input name="verboselog" type="checkbox" id="verboselog" value="yes" <?= empty($pconfig['verboselog']) ? '' : 'checked="checked"' ?> />
<strong><?= gettext("Enable verbose logging") ?></strong>
</td>
</tr>
<tr class="opt_field type_custom">
<td><i class="fa fa-info-circle text-muted"></i> <?=gettext("CURL options"); ?></td>
<td>
<input name="curl_ipresolve_v4" type="checkbox" id="curl_ipresolve_v4" value="yes" <?= empty($pconfig['curl_ipresolve_v4']) ? '' : 'checked="checked"' ?> />
<?= gettext("Force IPv4 resolving") ?><br />
<input name="curl_ssl_verifypeer" type="checkbox" id="curl_ssl_verifypeer" value="yes" <?= empty($pconfig['curl_ssl_verifypeer']) ? '' : 'checked="checked"' ?> />
<?= gettext("Verify SSL peer") ?>
</td>
</tr>
<tr>
<td><a id="help_for_username" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Username") ?></td>
<td>
<input name="username" type="text" id="username" value="<?= $pconfig['username'] ?>" />
<div class="hidden" for="help_for_username">
<?= gettext("Username is required for all types except Namecheap, FreeDNS and Custom Entries.");?>
<br /><?= gettext('Route 53: Enter your Access Key ID.') ?>
<br /><?= gettext('Duck DNS: Enter your Token.') ?>
<br /><?= gettext('For Custom Entries, Username and Password represent HTTP Authentication username and passwords.') ?>
</div>
</td>
</tr>
<tr>
<td><a id="help_for_password" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Password") ?></td>
<td>
<input name="password" type="password" id="password" value="<?= $pconfig['password'] ?>" />
<div class="hidden" for="help_for_password">
<?=gettext('FreeDNS (freedns.afraid.org): Enter your "Authentication Token" provided by FreeDNS.') ?>
<br /><?= gettext('Route 53: Enter your Secret Access Key.') ?>
<br /><?= gettext('Duck DNS: Leave blank.') ?>
</div>
</td>
</tr>
<tr class="opt_field type_route53">
<td><a id="help_for_zoneid" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Zone ID") ?></td>
<td>
<input name="zoneid" type="text" id="zoneid" value="<?= $pconfig['zoneid'] ?>" />
<div class="hidden" for="help_for_zoneid">
<?= gettext("Enter Zone ID that you received when you created your domain in Route 53.") ?>
</div>
</td>
</tr>
<tr class="opt_field type_custom">
<td><a id="help_for_updateurl" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Update URL") ?></td>
<td>
<input name="updateurl" type="text" id="updateurl" value="<?= $pconfig['updateurl'] ?>" />
<div class="hidden" for="help_for_updateurl">
<?= gettext("This is the only field required by for Custom Dynamic DNS, and is only used by Custom Entries.") ?>
<br />
<?= gettext("If you need the new IP to be included in the request, put %IP% in its place.") ?>
</div>
</td>
</tr>
<tr class="opt_field type_custom">
<td><a id="help_for_resultmatch" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?= gettext("Result Match") ?></td>
<td>
<textarea name="resultmatch" class="formpre" id="resultmatch" cols="65" rows="7"><?= $pconfig['resultmatch'] ?></textarea>
<div class="hidden" for="help_for_resultmatch">
<?= gettext("This field is only used by Custom Dynamic DNS Entries.") ?>
<br />
<?= gettext("This field should be identical to what your dynamic DNS Provider will return if the update succeeds, leave it blank to disable checking of returned results.");?>
<br />
<?= gettext("If you need the new IP to be included in the request, put %IP% in its place.") ?>
<br />
<?= gettext('If you need to include multiple possible values, separate them with a |. If your provider includes a |, escape it with \|') ?>
<br />
<?= gettext('Tabs (\t), newlines (\n) and carriage returns (\r) at the beginning or end of the returned results are removed before comparison.') ?>
</div>
</td>
</tr>
<tr class="opt_field type_route53">
<td><a id="help_for_ttl" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("TTL");?></td>
<td>
<input name="ttl" type="text" id="ttl" value="<?= $pconfig['ttl'] ?>" />
<div class="hidden" for="help_for_ttl">
<?= gettext("Choose TTL for your dns record.") ?>
</div>
</td>
</tr>
<tr>
<td><i class="fa fa-info-circle text-muted"></i> <?= gettext("Description") ?></td>
<td>
<input name="descr" type="text" id="descr" value="<?= $pconfig['descr'] ?>" />
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td>
<button name="submit" type="submit" class="btn btn-primary" value="save"><?= gettext('Save') ?></button>
<?php
if (isset($id)): ?>
<button name="force" type="submit" class="btn btn-primary" value="force"><?= gettext('Save and Force Update') ?></button>
<input name="id" type="hidden" value="<?= $id ?>" />
<?php
endif; ?>
<a href="services_dyndns.php" class="btn btn-default"><?= gettext('Cancel') ?></a>
</td>
</tr>
<tr>
<td colspan="2">
<?= sprintf(gettext('You must configure a DNS server in %sSystem: ' .
'General setup%s or allow the DNS server list to be overridden ' .
'by DHCP/PPP on WAN for dynamic DNS updates to work.'),
'<a href="system_general.php">', '</a>'); ?>
</td>
</tr>
</table>
</div>
</form>
</div>
</section>
</div>
</div>
</section>
<?php include("foot.inc"); ?>
<?php
$dyn_dns_status_title = gettext('Dynamic DNS');
$dyn_dns_status_title_link = 'services_dyndns.php';
<?php
/*
Copyright (C) 2014-2016 Deciso B.V.
Copyright (C) 2008 Ermal Luci
Copyright (C) 2013 Stanley P. Miller \ stan-qaz
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
INClUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
require_once("guiconfig.inc");
require_once("widgets/include/dyn_dns_status.inc");
require_once("services.inc");
require_once("interfaces.inc");
require_once("plugins.inc.d/dyndns.inc");
if (!isset($config['dyndnses']['dyndns'])) {
$config['dyndnses']['dyndns'] = array();
}
$a_dyndns = &$config['dyndnses']['dyndns'];
if (!empty($_REQUEST['getdyndnsstatus'])) {
$first_entry = true;
foreach ($a_dyndns as $dyndns) {
if ($first_entry) {
$first_entry = false;
} else {
// Put a vertical bar delimiter between the echoed HTML for each entry processed.
echo '|';
}
$filename = dyndns_cache_file($dyndns, 4);
$fdata = '';
if (!empty($dyndns['enable']) && file_exists($filename)) {
$ipaddr = get_dyndns_ip($dyndns['interface'], 4);
$fdata = @file_get_contents($filename);
}
$filename_v6 = dyndns_cache_file($dyndns, 6);
$fdata6 = '';
if (!empty($dyndns['enable']) && file_exists($filename_v6)) {
$ipv6addr = get_dyndns_ip($dyndns['interface'], 6);
$fdata6 = @file_get_contents($filename_v6);
}
if (!empty($fdata)) {
$cached_ip_s = explode('|', $fdata);
$cached_ip = $cached_ip_s[0];
echo sprintf(
'<font color="%s">%s</font>',
$ipaddr != $cached_ip ? 'red' : 'green',
htmlspecialchars($cached_ip)
);
} elseif (!empty($fdata6)) {
$cached_ipv6_s = explode('|', $fdata6);
$cached_ipv6 = $cached_ipv6_s[0];
echo sprintf(
'<font color="%s">%s</font>',
$ipv6addr != $cached_ipv6 ? 'red' : 'green',
htmlspecialchars($cached_ipv6)
);
} else {
echo gettext('N/A');
}
}
exit;
}
?>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th><?=gettext("Interface");?></th>
<th><?=gettext("Service");?></th>
<th><?=gettext("Hostname");?></th>
<th><?=gettext("Cached IP");?></th>
</tr>
</thead>
<tbody>
<?php
$iflist = get_configured_interface_with_descr();
$types = dyndns_list();
$groupslist = return_gateway_groups_array();
foreach ($a_dyndns as $i => $dyndns) :?>
<tr ondblclick="document.location='services_dyndns_edit.php?id=<?=$i;?>'">
<td <?= isset($dyndns['enable']) ? '' : 'class="text-muted"' ?>>
<?php
foreach ($iflist as $if => $ifdesc) {
if ($dyndns['interface'] == $if) {
echo "{$ifdesc}";
break;
}
}
foreach ($groupslist as $if => $group) {
if ($dyndns['interface'] == $if) {
echo "{$if}";
break;
}
}?>
</td>
<td <?= isset($dyndns['enable']) ? '' : 'class="text-muted"' ?>>
<?php
if (isset($types[$dyndns['type']])) {
echo htmlspecialchars($types[$dyndns['type']]);
} else {
echo htmlspecialchars($dyndns['type']);
}
?>
</td>
<td <?= isset($dyndns['enable']) ? '' : 'class="text-muted"' ?>>
<?= htmlspecialchars($dyndns['host']) ?>
</td>
<td <?= isset($dyndns['enable']) ? '' : 'class="text-muted"' ?>>
<div id='dyndnsstatus<?=$i;?>'>
<?= gettext('Checking...') ?>
</div>
</td>
</tr>
<?php
endforeach;?>
</tbody>
</table>
<script type="text/javascript">
function dyndns_getstatus()
{
scroll(0,0);
var url = "/widgets/widgets/dyn_dns_status.widget.php";
var pars = 'getdyndnsstatus=yes';
jQuery.ajax(url, {type: 'get', data: pars, complete: dyndnscallback});
// Refresh the status every 5 minutes
setTimeout('dyndns_getstatus()', 5*60*1000);
}
function dyndnscallback(transport)
{
// The server returns a string of statuses separated by vertical bars
var responseStrings = transport.responseText.split("|");
for (var count=0; count<responseStrings.length; count++) {
var divlabel = '#dyndnsstatus' + count;
jQuery(divlabel).prop('innerHTML',responseStrings[count]);
}
}
$( document ).ready(function() {
// Do the first status check 2 seconds after the dashboard opens
setTimeout('dyndns_getstatus()', 2000);
});
</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment