diff --git a/dns/rfc2136/Makefile b/dns/rfc2136/Makefile new file mode 100644 index 000000000..bfa4e884a --- /dev/null +++ b/dns/rfc2136/Makefile @@ -0,0 +1,8 @@ +PLUGIN_NAME= rfc2136 +PLUGIN_VERSION= 1.0 +PLUGIN_COMMENT= RFC-2136 Support +PLUGIN_MAINTAINER= franco@opnsense.org +PLUGIN_DEPENDS= bind911 +PLUGIN_DEVEL= yes + +.include "../../Mk/plugins.mk" diff --git a/dns/rfc2136/src/etc/inc/plugins.inc.d/rfc2136.inc b/dns/rfc2136/src/etc/inc/plugins.inc.d/rfc2136.inc new file mode 100644 index 000000000..ebfd12eb3 --- /dev/null +++ b/dns/rfc2136/src/etc/inc/plugins.inc.d/rfc2136.inc @@ -0,0 +1,248 @@ + + Copyright (C) 2010 Ermal Luci + Copyright (C) 2005-2006 Colin Smith + Copyright (C) 2003-2004 Manuel Kasper + 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. +*/ + +function rfc2136_configure() +{ + return array( + 'bootup' => array('rfc2136_configure_do'), + 'local' => array('rfc2136_configure_do'), + 'newwanip' => array('rfc2136_configure_do:2'), + ); +} + +function rfc2136_enabled() +{ + global $config; + + if (isset($config['dnsupdates']['dnsupdate'])) { + foreach ($config['dnsupdates']['dnsupdate'] as $dnsupdate) { + if (isset($dnsupdate['enable'])) { + return true; + } + } + } + + return false; +} + +function rfc2136_services() +{ + global $config; + + $services = array(); + + if (rfc2136_enabled()) { + $services[] = array( + 'description' => gettext('RFC 2136'), + 'configd' => array( + 'restart' => array('rfc2136 reload'), + ), + 'nocheck' => true, + 'name' => 'rfc2136', + ); + } + + return $services; +} + +function rfc2136_cron() +{ + $jobs = array(); + + if (rfc2136_enabled()) { + $jobs[]['autocron'] = array('/usr/local/etc/rc.rfc2136', '16', '1'); + } + + return $jobs; +} + +function rfc2136_cache_file($dnsupdate, $ipver = 4) +{ + $ipver = $ipver == 6 ? '_v6' : ''; + + return "/var/cache/rfc2136_{$dnsupdate['interface']}_{$dnsupdate['host']}_{$dnsupdate['server']}{$ipver}.cache"; +} + +function rfc2136_configure_do($verbose = false, $int = '', $updatehost = '', $forced = false) +{ + global $config; + + if (!rfc2136_enabled()) { + return; + } + + $notify_text = ''; + + if ($verbose) { + echo 'Configuring RFC 2136 clients...'; + flush(); + } + + foreach ($config['dnsupdates']['dnsupdate'] as $i => $dnsupdate) { + if (!isset($dnsupdate['enable'])) { + continue; + } elseif (!empty($int) && $int != $dnsupdate['interface']) { + continue; + } elseif (!empty($updatehost) && ($updatehost != $dnsupdate['host'])) { + continue; + } + + $currentTime = time(); + + $keyname = $dnsupdate['keyname']; + /* trailing dot */ + if (substr($keyname, -1) != ".") { + $keyname .= "."; + } + + $hostname = $dnsupdate['host']; + /* trailing dot */ + if (substr($hostname, -1) != ".") { + $hostname .= "."; + } + + /* write private key file + this is dumb - public and private keys are the same for HMAC-MD5, + but nsupdate insists on having both */ + $fd = fopen("/var/etc/K{$i}{$keyname}+157+00000.private", "w"); + $privkey = << $maxCacheAgeSecs) || $forced) { + $upinst .= "update delete {$dnsupdate['host']}. A\n"; + $upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} A {$wanip}\n"; + $notify_text .= sprintf(gettext('Dynamic DNS updated IP Address (A) for %s on %s to %s'), $dnsupdate['host'], strtoupper($dnsupdate['interface']), $wanip) . "\n"; + @file_put_contents($cacheFile, "{$wanip}|{$currentTime}"); + log_error("Dynamic DNS: updating cache file {$cacheFile}: {$wanip}"); + $need_update = true; + } else { + log_error("Dynamic DNS: Not updating {$dnsupdate['host']} A record because the IP address has not changed."); + } + } else { + @unlink($cacheFile); + } + } + + if (empty($dnsupdate['recordtype']) || $dnsupdate['recordtype'] == 'AAAA') { + $cacheFile6 = rfc2136_cache_file($dnsupdate, 6); + if (file_exists($cacheFile6)) { + list($cachedipv6, $cacheTimev6) = explode('|', file_get_contents($cacheFile6)); + } else { + list($cachedipv6, $cacheTimev6) = array('', ''); + } + if (isset($dnsupdate['usepublicip'])) { + $wanipv6 = get_dyndns_ip($dnsupdate['interface'], 6); + } else { + $wanipv6 = get_interface_ipv6($dnsupdate['interface']); + } + if (is_ipaddrv6($wanipv6)) { + if (($wanipv6 != $cachedipv6) || (($currentTime - $cacheTimev6) > $maxCacheAgeSecs) || $forced) { + $upinst .= "update delete {$dnsupdate['host']}. AAAA\n"; + $upinst .= "update add {$dnsupdate['host']}. {$dnsupdate['ttl']} AAAA {$wanipv6}\n"; + $notify_text .= sprintf(gettext('Dynamic DNS updated IPv6 Address (AAAA) for %s on %s to %s'), $dnsupdate['host'], strtoupper($dnsupdate['interface']), $wanipv6) . "\n"; + @file_put_contents($cacheFile6, "{$wanipv6}|{$currentTime}"); + log_error("Dynamic DNS: updating cache file {$cacheFile6}: {$wanipv6}"); + $need_update = true; + } else { + log_error("Dynamic DNS: Not updating {$dnsupdate['host']} AAAA record because the IPv6 address has not changed."); + } + } else { + @unlink($cacheFile6); + } + } + + $upinst .= "\n"; /* mind that trailing newline! */ + + if ($need_update) { + @file_put_contents("/var/etc/nsupdatecmds{$i}", $upinst); + unset($upinst); + /* invoke nsupdate */ + $cmd = "/usr/local/bin/nsupdate -k /var/etc/K{$i}{$keyname}+157+00000.key"; + if (isset($dnsupdate['usetcp'])) + $cmd .= " -v"; + $cmd .= " /var/etc/nsupdatecmds{$i}"; + mwexec_bg($cmd); + unset($cmd); + } + } + + if (!empty($notify_text)) { + notify_all_remote($notify_text); + } + + if ($verbose) { + echo "done.\n"; + } +} diff --git a/dns/rfc2136/src/etc/rc.rfc2136 b/dns/rfc2136/src/etc/rc.rfc2136 new file mode 100755 index 000000000..e86e4d25a --- /dev/null +++ b/dns/rfc2136/src/etc/rc.rfc2136 @@ -0,0 +1,51 @@ +#!/usr/local/bin/php + + + Services: RFC 2136 clients + + services_rfc2136.php* + services_rfc2136_edit.php* + + + diff --git a/dns/rfc2136/src/opnsense/mvc/app/models/OPNsense/RFC2136/Menu/Menu.xml b/dns/rfc2136/src/opnsense/mvc/app/models/OPNsense/RFC2136/Menu/Menu.xml new file mode 100644 index 000000000..531e449ad --- /dev/null +++ b/dns/rfc2136/src/opnsense/mvc/app/models/OPNsense/RFC2136/Menu/Menu.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/dns/rfc2136/src/opnsense/service/conf/actions.d/actions_rfc2136.conf b/dns/rfc2136/src/opnsense/service/conf/actions.d/actions_rfc2136.conf new file mode 100644 index 000000000..10d4ea5f0 --- /dev/null +++ b/dns/rfc2136/src/opnsense/service/conf/actions.d/actions_rfc2136.conf @@ -0,0 +1,6 @@ +[reload] +command:/usr/local/etc/rc.rfc2136 +description:RFC 2136 Update +parameters:%s +type:script +message:updating rfc2136 %s diff --git a/dns/rfc2136/src/www/services_rfc2136.php b/dns/rfc2136/src/www/services_rfc2136.php new file mode 100644 index 000000000..f0587da89 --- /dev/null +++ b/dns/rfc2136/src/www/services_rfc2136.php @@ -0,0 +1,212 @@ + gettext('Add'), 'href' => 'services_rfc2136_edit.php'), +); + +?> + + + + +
+
+
+ 0) print_input_errors($input_errors); ?> +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+ "> + "> + + + + $cached_ip) { + echo ""; + } else { + echo ""; + } + echo htmlspecialchars($cached_ip); + echo ""; + } else { + echo 'IPv4: ' . gettext('N/A'); + } + echo "
"; + $filename6 = rfc2136_cache_file($rfc2136, 6); + if (file_exists($filename6) && !empty($rfc2136['enable']) && (empty($rfc2136['recordtype']) || $rfc2136['recordtype'] == 'AAAA')) { + echo "IPv6: "; + if (isset($rfc2136['usepublicip'])) { + $ipaddr = get_dyndns_ip($rfc2136['interface'], 6); + } else { + $ipaddr = get_interface_ipv6($rfc2136['interface']); + } + $cached_ip_s = explode("|", file_get_contents($filename6)); + $cached_ip = $cached_ip_s[0]; + if ($ipaddr <> $cached_ip) { + echo ""; + } else { + echo ""; + } + echo htmlspecialchars($cached_ip); + echo ""; + } else { + echo 'IPv6: ' . gettext('N/A'); + }?> +
+ + + + +
+
+
+
+
+
+
+
+ diff --git a/dns/rfc2136/src/www/services_rfc2136_edit.php b/dns/rfc2136/src/www/services_rfc2136_edit.php new file mode 100644 index 000000000..68fcf22a6 --- /dev/null +++ b/dns/rfc2136/src/www/services_rfc2136_edit.php @@ -0,0 +1,273 @@ + + + +
+
+
+ 0) print_input_errors($input_errors); ?> + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ /> +
+ +
+ + +
+ />   + />   + /> + +
() + +
+ + +
+ />   + />   + /> +
+ + +
+ +
+ " /> + +
+ " /> + +
+ +
  + + + + + + +
+ ', '');?> +
+
+
+
+
+
+
+
+ diff --git a/dns/rfc2136/src/www/widgets/include/rfc2136.inc b/dns/rfc2136/src/www/widgets/include/rfc2136.inc new file mode 100644 index 000000000..c143db6dd --- /dev/null +++ b/dns/rfc2136/src/www/widgets/include/rfc2136.inc @@ -0,0 +1,4 @@ + + 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/rfc2136.inc"); +require_once("services.inc"); +require_once("interfaces.inc"); +require_once("plugins.inc.d/rfc2136.inc"); + +if (!isset($config['dnsupdates']['dnsupdate'])) { + $config['dnsupdates']['dnsupdate'] = array(); +} + +$a_rfc2136 = &$config['dnsupdates']['dnsupdate']; + +if (!empty($_REQUEST['getrfc2136status'])) { + $first_entry = true; + foreach ($a_rfc2136 as $rfc2136) { + if ($first_entry) { + $first_entry = false; + } else { + // Put a vertical bar delimiter between the echoed HTML for each entry processed. + echo '|'; + } + + $filename = rfc2136_cache_file($rfc2136, 4); + $fdata = ''; + if (!empty($rfc2136['enable']) && (empty($rfc2136['recordtype']) || $rfc2136['recordtype'] == 'A') && file_exists($filename)) { + $ipaddr = get_dyndns_ip($rfc2136['interface'], 4); + $fdata = @file_get_contents($filename); + } + + $filename_v6 = rfc2136_cache_file($rfc2136, 6); + $fdata6 = ''; + if (!empty($rfc2136['enable']) && (empty($rfc2136['recordtype']) || $rfc2136['recordtype'] == 'AAAA') && file_exists($filename_v6)) { + $ipv6addr = get_dyndns_ip($rfc2136['interface'], 6); + $fdata6 = @file_get_contents($filename_v6); + } + + if (!empty($fdata)) { + $cached_ip_s = explode('|', $fdata); + $cached_ip = $cached_ip_s[0]; + echo sprintf( + 'IPv4: %s', + $ipaddr != $cached_ip ? 'red' : 'green', + htmlspecialchars($cached_ip) + ); + } else { + echo 'IPv4: ' . gettext('N/A'); + } + + echo '
'; + + if (!empty($fdata6)) { + $cached_ipv6_s = explode('|', $fdata6); + $cached_ipv6 = $cached_ipv6_s[0]; + echo sprintf( + 'IPv6: %s', + $ipv6addr != $cached_ipv6 ? 'red' : 'green', + htmlspecialchars($cached_ipv6) + ); + } else { + echo 'IPv6: ' . gettext('N/A'); + } + } + exit; +} + +?> + + + + + + + + + + + + $rfc2136) :?> + + + + + + + + +
> + $ifdesc) { + if ($rfc2136['interface'] == $if) { + echo "{$ifdesc}"; + break; + } + } + foreach ($groupslist as $if => $group) { + if ($rfc2136['interface'] == $if) { + echo "{$if}"; + break; + } + }?> + > + + > + + > +
+ +
+
+