mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-15 09:04:39 +00:00
unbound: overrides: migrate to mvc model (#5488)
* unbound: overrides: migrate to mvc model * unbound: overrides: generate host_entries via model, revert template generation * unbound: overrides migration: fix missing include * unbound: overrides: clean up Co-authored-by: Stephan de Wit <stephan.de.wit@deciso.com>
This commit is contained in:
parent
4ca55d9dc6
commit
161d24650b
12
plist
12
plist
@ -377,9 +377,13 @@
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/Api/SettingsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/DnsblController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/DotController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/OverridesController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/StatsController.php
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogDot.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dnsbl.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogDomainOverride.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogHostAlias.xml
|
||||
/usr/local/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogHostOverride.xml
|
||||
/usr/local/opnsense/mvc/app/library/Google/API/Drive.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/API.php
|
||||
/usr/local/opnsense/mvc/app/library/OPNsense/Auth/AuthenticationFactory.php
|
||||
@ -564,6 +568,7 @@
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/ACL/ACL.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Menu/Menu.xml
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Migrations/M1_0_0.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Migrations/M1_0_1.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Unbound.php
|
||||
/usr/local/opnsense/mvc/app/models/OPNsense/Unbound/Unbound.xml
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/CaptivePortal/clients.volt
|
||||
@ -608,6 +613,7 @@
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/TrafficShaper/statistics.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/dnsbl.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/dot.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/overrides.volt
|
||||
/usr/local/opnsense/mvc/app/views/OPNsense/Unbound/stats.volt
|
||||
/usr/local/opnsense/mvc/app/views/layout_partials/base_dialog.volt
|
||||
/usr/local/opnsense/mvc/app/views/layout_partials/base_dialog_processing.volt
|
||||
@ -989,6 +995,9 @@
|
||||
/usr/local/opnsense/service/templates/OPNsense/Syslog/syslog-ng.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/+TARGETS
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/blocklists.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/host_entries.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/dot.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/miscellaneous.conf
|
||||
/usr/local/opnsense/service/templates/OPNsense/Unbound/core/root.min.hints
|
||||
@ -1804,9 +1813,6 @@
|
||||
/usr/local/www/services_unbound.php
|
||||
/usr/local/www/services_unbound_acls.php
|
||||
/usr/local/www/services_unbound_advanced.php
|
||||
/usr/local/www/services_unbound_domainoverride_edit.php
|
||||
/usr/local/www/services_unbound_host_edit.php
|
||||
/usr/local/www/services_unbound_overrides.php
|
||||
/usr/local/www/status_dhcp_leases.php
|
||||
/usr/local/www/status_dhcpv6_leases.php
|
||||
/usr/local/www/status_habackup.php
|
||||
|
||||
@ -219,14 +219,7 @@ EOF;
|
||||
}
|
||||
}
|
||||
|
||||
/* allow DNS Rebind for forwarded domains */
|
||||
if (!empty($config['unbound']['domainoverrides'])) {
|
||||
$private_domains = "# Set private domains in case authoritative name server returns a Private IP address\n";
|
||||
$private_domains .= unbound_add_domain_overrides(true);
|
||||
}
|
||||
|
||||
unbound_add_host_entries($ifconfig_details);
|
||||
unbound_add_domain_overrides();
|
||||
unbound_acls_config();
|
||||
|
||||
$port = is_port($config['unbound']['port']) ? $config['unbound']['port'] : "53";
|
||||
@ -359,7 +352,9 @@ prefetch-key: {$prefetch_key}
|
||||
|
||||
# DNS Rebinding
|
||||
{$private_addr}
|
||||
{$private_domains}
|
||||
|
||||
# Private domains (DNS Rebinding)
|
||||
include: /var/unbound/private_domains.conf
|
||||
|
||||
# Access lists
|
||||
include: /var/unbound/access_lists.conf
|
||||
@ -370,9 +365,6 @@ include: /var/unbound/host_entries.conf
|
||||
# DHCP leases (if configured)
|
||||
{$include_dhcpleases}
|
||||
|
||||
# Domain overrides
|
||||
include: /var/unbound/domainoverrides.conf
|
||||
|
||||
# Custom includes
|
||||
include: /var/unbound/etc/*.conf
|
||||
|
||||
@ -439,56 +431,6 @@ function unbound_configure_do($verbose = false, $interface = '')
|
||||
}
|
||||
}
|
||||
|
||||
function unbound_add_domain_overrides($pvt = false)
|
||||
{
|
||||
global $config;
|
||||
|
||||
$domains = config_read_array('unbound', 'domainoverrides');
|
||||
|
||||
usort($domains, function ($a, $b) {
|
||||
return strcasecmp($a['domain'], $b['domain']);
|
||||
});
|
||||
|
||||
$result = array();
|
||||
$forward_local = '';
|
||||
|
||||
foreach ($domains as $domain) {
|
||||
$domain_key = current($domain);
|
||||
if (!isset($result[$domain_key])) {
|
||||
$result[$domain_key] = array();
|
||||
}
|
||||
$result[$domain_key][] = $domain['ip'];
|
||||
}
|
||||
|
||||
$domain_entries = '';
|
||||
foreach ($result as $domain => $ips) {
|
||||
if ($pvt == true) {
|
||||
$domain_entries .= "domain-insecure: \"$domain\"\n";
|
||||
if (preg_match('/.+\.(in-addr|ip6)\.arpa\.?$/', $domain)) {
|
||||
$domain_entries .= "local-zone: \"$domain\" typetransparent\n";
|
||||
} elseif (!isset($config['system']['webgui']['nodnsrebindcheck'])) {
|
||||
$domain_entries .= "private-domain: \"$domain\"\n";
|
||||
}
|
||||
} else {
|
||||
$domain_entries .= "forward-zone:\n";
|
||||
$domain_entries .= "\tname: \"$domain\"\n";
|
||||
foreach ($ips as $ip) {
|
||||
if (strpos($ip, '127.') === 0 || $ip == '::1') {
|
||||
$forward_local = "server:\n\tdo-not-query-localhost: no\n";
|
||||
}
|
||||
$domain_entries .= "\tforward-addr: $ip\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($pvt == true) {
|
||||
return $domain_entries;
|
||||
} else {
|
||||
$domain_entries .= $forward_local;
|
||||
file_put_contents('/var/unbound/domainoverrides.conf', $domain_entries);
|
||||
}
|
||||
}
|
||||
|
||||
function unbound_add_host_entries($ifconfig_details = null)
|
||||
{
|
||||
global $config;
|
||||
@ -577,55 +519,59 @@ function unbound_add_host_entries($ifconfig_details = null)
|
||||
unset($tmp_known_domains); // remove temporary variable
|
||||
}
|
||||
|
||||
if (isset($config['unbound']['hosts'])) {
|
||||
foreach ($config['unbound']['hosts'] as $host) {
|
||||
$aliases = array(array(
|
||||
'domain' => $host['domain'],
|
||||
'descr' => $host['descr'],
|
||||
'host' => $host['host'],
|
||||
));
|
||||
$unbound_mdl = new \OPNsense\Unbound\Unbound();
|
||||
$hosts = iterator_to_array($unbound_mdl->hosts->host->iterateItems());
|
||||
$aliases = iterator_to_array($unbound_mdl->aliases->alias->iterateItems());
|
||||
|
||||
if (!empty($host['aliases']['item'])) {
|
||||
foreach ($host['aliases']['item'] as $alias) {
|
||||
$aliases[] = array(
|
||||
'domain' => !empty($alias['domain']) ? $alias['domain'] : $aliases[0]['domain'],
|
||||
'descr' => !empty($alias['descr']) ? $alias['descr'] : $aliases[0]['descr'],
|
||||
'host' => !empty($alias['host']) ? $alias['host'] : $aliases[0]['host'],
|
||||
);
|
||||
}
|
||||
}
|
||||
if (!empty($hosts)) {
|
||||
foreach ($hosts as $host) {
|
||||
if ($host->enabled == '1') {
|
||||
$tmp_aliases = array(array(
|
||||
'domain' => (string)$host->domain,
|
||||
'description' => (string)$host->description,
|
||||
'hostname' => (string)$host->hostname
|
||||
));
|
||||
|
||||
/* Backwards compatibility for records created before introducing RR types. */
|
||||
if (!isset($host['rr'])) {
|
||||
$host['rr'] = (is_ipaddrv6($host['ip'])) ? 'AAAA' : 'A';
|
||||
}
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
if ($alias['host'] != '') {
|
||||
$alias['host'] .= '.';
|
||||
}
|
||||
|
||||
switch ($host['rr']) {
|
||||
case 'A':
|
||||
case 'AAAA':
|
||||
/* Handle wildcard entries which have "*" as a hostname. Since we added a . above, we match on "*.". */
|
||||
if ($alias['host'] == '*.') {
|
||||
$unbound_entries .= "local-zone: \"{$alias['domain']}\" redirect\n";
|
||||
$unbound_entries .= "local-data: \"{$alias['domain']} IN {$host['rr']} {$host['ip']}\"\n";
|
||||
} else {
|
||||
$unbound_entries .= "local-data-ptr: \"{$host['ip']} {$alias['host']}{$alias['domain']}\"\n";
|
||||
$unbound_entries .= "local-data: \"{$alias['host']}{$alias['domain']} IN {$host['rr']} {$host['ip']}\"\n";
|
||||
if (!empty($aliases)) {
|
||||
foreach ($aliases as $alias) {
|
||||
if ($alias->enabled == '1' && $alias->host == $host->getAttribute('uuid')) {
|
||||
$tmp_aliases[] = array(
|
||||
'domain' => !empty((string)$alias->domain) ? $alias->domain : $tmp_aliases[0]['domain'],
|
||||
'description' => !empty((string)$alias->description) ? $alias->description : $tmp_aliases[0]['description'],
|
||||
'hostname' => !empty((string)$alias->hostname) ? $alias->hostname : $tmp_aliases[0]['hostname']
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'MX':
|
||||
$unbound_entries .= "local-data: \"{$alias['host']}{$alias['domain']} IN MX {$host['mxprio']} {$host['mx']}\"\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($alias['descr']) && isset($config['unbound']['txtsupport'])) {
|
||||
$unbound_entries .= "local-data: '{$alias['host']}{$alias['domain']} TXT \"" . addslashes($alias['descr']) . "\"'\n";
|
||||
foreach ($tmp_aliases as $alias) {
|
||||
if ($alias['hostname'] != '') {
|
||||
$alias['hostname'] .= '.';
|
||||
}
|
||||
|
||||
switch ($host->rr) {
|
||||
case 'A':
|
||||
case 'AAAA':
|
||||
/* Handle wildcard entries which have "*" as a hostname. Since we added a . above, we match on "*.". */
|
||||
if ($alias['hostname'] == '*.') {
|
||||
$unbound_entries .= "local-zone: \"{$alias['domain']}\" redirect\n";
|
||||
$unbound_entries .= "local-data: \"{$alias['domain']} IN {$host->rr} {$host->server}\"\n";
|
||||
} else {
|
||||
$unbound_entries .= "local-data-ptr: \"{$host->server} {$alias['hostname']}{$alias['domain']}\"\n";
|
||||
$unbound_entries .= "local-data: \"{$alias['hostname']}{$alias['domain']} IN {$host->rr} {$host->server}\"\n";
|
||||
}
|
||||
break;
|
||||
case 'MX':
|
||||
$unbound_entries .= "local-data: \"{$alias['hostname']}{$alias['domain']} IN MX {$host->mxprio} {$host->mx}\"\n";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!empty($alias['description']) && isset($config['unbound']['txtsupport'])) {
|
||||
$unbound_entries .= "local-data: '{$alias['hostname']}{$alias['domain']} TXT \"" . addslashes($alias['description']) . "\"'\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -65,4 +65,139 @@ class SettingsController extends ApiMutableModelControllerBase
|
||||
{
|
||||
return $this->toggleBase('dots.dot', $uuid, $enabled);
|
||||
}
|
||||
|
||||
/* Host overrides */
|
||||
|
||||
public function searchHostOverrideAction()
|
||||
{
|
||||
return $this->searchBase(
|
||||
'hosts.host',
|
||||
['enabled', 'hostname', 'domain', 'rr', 'mxprio', 'mx', 'server', 'description'],
|
||||
"sequence"
|
||||
);
|
||||
}
|
||||
|
||||
public function getHostOverrideAction($uuid = null)
|
||||
{
|
||||
return $this->getBase('host', 'hosts.host', $uuid);
|
||||
}
|
||||
|
||||
public function addHostOverrideAction()
|
||||
{
|
||||
return $this->addBase('host', 'hosts.host');
|
||||
}
|
||||
|
||||
public function delHostOverrideAction($uuid)
|
||||
{
|
||||
/* Make sure the linked aliases are deleted as well. */
|
||||
$node = $this->getModel();
|
||||
foreach ($node->aliases->alias->iterateItems() as $alias_uuid => $alias) {
|
||||
if ($alias->host == $uuid) {
|
||||
$this->delBase('aliases.alias', $alias_uuid);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->delBase('hosts.host', $uuid);
|
||||
}
|
||||
|
||||
public function setHostOverrideAction($uuid)
|
||||
{
|
||||
return $this->setBase('host', 'hosts.host', $uuid);
|
||||
}
|
||||
|
||||
public function toggleHostOverrideAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase('hosts.host', $uuid, $enabled);
|
||||
}
|
||||
|
||||
/* Aliases for hosts */
|
||||
|
||||
public function searchHostAliasAction()
|
||||
{
|
||||
$host = $this->request->get('host');
|
||||
$filter_func = null;
|
||||
if (!empty($host)) {
|
||||
$filter_func = function ($record) use ($host) {
|
||||
return $record->host == $host;
|
||||
};
|
||||
}
|
||||
return $this->searchBase(
|
||||
'aliases.alias',
|
||||
['enabled', 'host', 'hostname', 'domain'],
|
||||
"sequence",
|
||||
$filter_func
|
||||
);
|
||||
}
|
||||
|
||||
public function getHostAliasAction($uuid = null)
|
||||
{
|
||||
$host_uuid = $this->request->get('host');
|
||||
$result = $this->getBase('alias', 'aliases.alias', $uuid);
|
||||
if (empty($uuid) && !empty($host_uuid)) {
|
||||
foreach($result['alias']['host'] as $key => &$value) {
|
||||
if ($key == $host_uuid) {
|
||||
$value['selected'] = 1;
|
||||
} else {
|
||||
$value['selected'] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function addHostAliasAction()
|
||||
{
|
||||
return $this->addBase('alias', 'aliases.alias');
|
||||
}
|
||||
|
||||
public function delHostAliasAction($uuid)
|
||||
{
|
||||
return $this->delBase('aliases.alias', $uuid);
|
||||
}
|
||||
|
||||
public function setHostAliasAction($uuid)
|
||||
{
|
||||
return $this->setBase('alias', 'aliases.alias');
|
||||
}
|
||||
|
||||
public function toggleHostAliasAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase('aliases.alias', $uuid, $enabled);
|
||||
}
|
||||
|
||||
/* Domain overrides */
|
||||
|
||||
public function searchDomainOverrideAction()
|
||||
{
|
||||
return $this->searchBase(
|
||||
'domains.domain',
|
||||
['enabled', 'domain', 'server', 'description'],
|
||||
"sequence"
|
||||
);
|
||||
}
|
||||
|
||||
public function getDomainOverrideAction($uuid = null)
|
||||
{
|
||||
return $this->getBase('domain', 'domains.domain', $uuid);
|
||||
}
|
||||
|
||||
public function addDomainOverrideAction()
|
||||
{
|
||||
return $this->addBase('domain', 'domains.domain');
|
||||
}
|
||||
|
||||
public function delDomainOverrideAction($uuid)
|
||||
{
|
||||
return $this->delBase('domains.domain', $uuid);
|
||||
}
|
||||
|
||||
public function setDomainOverrideAction($uuid)
|
||||
{
|
||||
return $this->setBase('domain', 'domains.domain', $uuid);
|
||||
}
|
||||
|
||||
public function toggleDomainOverrideAction($uuid, $enabled = null)
|
||||
{
|
||||
return $this->toggleBase('domains.domain', $uuid, $enabled);
|
||||
}
|
||||
}
|
||||
|
||||
42
src/opnsense/mvc/app/controllers/OPNsense/Unbound/OverridesController.php
Executable file
42
src/opnsense/mvc/app/controllers/OPNsense/Unbound/OverridesController.php
Executable file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Stephan de Wit <stephan.de.wit@deciso.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Unbound;
|
||||
|
||||
use OPNsense\Base\IndexController;
|
||||
|
||||
class OverridesController extends IndexController
|
||||
{
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->pick('OPNsense/Unbound/overrides');
|
||||
$this->view->formDialogHostOverride = $this->getForm("dialogHostOverride");
|
||||
$this->view->formDialogHostAlias = $this->getForm("dialogHostAlias");
|
||||
$this->view->formDialogDomainOverride = $this->getForm("dialogDomainOverride");
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>domain.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this domain override</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>domain.domain</id>
|
||||
<label>Domain</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
Domain to override (NOTE: this does not have to be a valid TLD!),
|
||||
e.g. 'test' or 'mycompany.localdomain' or '1.168.192.in-addr.arpa'
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>domain.server</id>
|
||||
<label>IP address</label>
|
||||
<type>text</type>
|
||||
<help>
|
||||
IP address of the authoritative DNS server for this domain,
|
||||
e.g. '192.168.100.100'. To use a nondefault port for communication,
|
||||
append an '@' with the port number.
|
||||
</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>domain.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
<help>You may enter a description here for your reference (not parsed).</help>
|
||||
</field>
|
||||
</form>
|
||||
26
src/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogHostAlias.xml
Executable file
26
src/opnsense/mvc/app/controllers/OPNsense/Unbound/forms/dialogHostAlias.xml
Executable file
@ -0,0 +1,26 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>alias.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable this alias for the selected host</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>alias.host</id>
|
||||
<label>Host override</label>
|
||||
<type>dropdown</type>
|
||||
<help>Select the associated host override to apply this alias on</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>alias.hostname</id>
|
||||
<label>Host</label>
|
||||
<type>text</type>
|
||||
<help>Name of the host, without the domain part. Use "*" to create a wildcard entry.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>alias.domain</id>
|
||||
<label>Domain</label>
|
||||
<type>text</type>
|
||||
<help>Domain of the host, e.g. example.com</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -0,0 +1,50 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>host.enabled</id>
|
||||
<label>Enabled</label>
|
||||
<type>checkbox</type>
|
||||
<help>Enable the override for this host</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.hostname</id>
|
||||
<label>Host</label>
|
||||
<type>text</type>
|
||||
<help>Name of the host, without the domain part. Use "*" to create a wildcard entry.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.domain</id>
|
||||
<label>Domain</label>
|
||||
<type>text</type>
|
||||
<help>Domain of the host, e.g. example.com</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.rr</id>
|
||||
<label>Type</label>
|
||||
<type>dropdown</type>
|
||||
<help>Type of resource record, e.g. A or AAAA for IPv4 or IPv6 addresses</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.mxprio</id>
|
||||
<label>MX Priority</label>
|
||||
<type>text</type>
|
||||
<help>Priority of MX record, e.g. 10</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.mx</id>
|
||||
<label>MX Host</label>
|
||||
<type>text</type>
|
||||
<help>Host name of MX host, e.g. mail.example.com</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.server</id>
|
||||
<label>IP address</label>
|
||||
<type>text</type>
|
||||
<help>IP address of the host, e.g. 192.168.100.100 or fd00:abcd::1</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>host.description</id>
|
||||
<label>Description</label>
|
||||
<type>text</type>
|
||||
<help>You may enter a description here for your reference (not parsed)</help>
|
||||
</field>
|
||||
</form>
|
||||
@ -57,10 +57,15 @@ class HostnameField extends BaseField
|
||||
private $internalAsList = false;
|
||||
|
||||
/**
|
||||
* @var bool wildcard (any) enabled
|
||||
* @var bool IP address allowed
|
||||
*/
|
||||
protected $internalIpAllowed = true;
|
||||
|
||||
/**
|
||||
* @var bool wildcard (*) enabled
|
||||
*/
|
||||
protected $internalWildcardAllowed = false;
|
||||
|
||||
/**
|
||||
* ip addresses allowed
|
||||
* @param string $value Y/N
|
||||
@ -74,6 +79,15 @@ class HostnameField extends BaseField
|
||||
}
|
||||
}
|
||||
|
||||
public function setWildcardAllowed($value)
|
||||
{
|
||||
if (trim($value) == "Y") {
|
||||
$this->internalWildcardAllowed = true;
|
||||
} else {
|
||||
$this->internalWildcardAllowed = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* always trim hostnames
|
||||
* @param string $value
|
||||
@ -132,11 +146,13 @@ class HostnameField extends BaseField
|
||||
{
|
||||
$validators = parent::getValidators();
|
||||
if ($this->internalValue != null) {
|
||||
$validators[] = new HostValidator(array(
|
||||
'message' => $this->internalValidationMessage,
|
||||
'split' => $this->internalFieldSeparator,
|
||||
'allowip' => $this->internalIpAllowed
|
||||
));
|
||||
if ($this->internalValue != "*" || $this->internalWildcardAllowed == false) {
|
||||
$validators[] = new HostValidator(array(
|
||||
'message' => $this->internalValidationMessage,
|
||||
'split' => $this->internalFieldSeparator,
|
||||
'allowip' => $this->internalIpAllowed
|
||||
));
|
||||
}
|
||||
}
|
||||
return $validators;
|
||||
}
|
||||
|
||||
@ -17,20 +17,13 @@
|
||||
<pattern>services_unbound_advanced.php*</pattern>
|
||||
</patterns>
|
||||
</page-services-dnsresolver-advanced>
|
||||
<page-services-dnsresolver-editdomainoverride>
|
||||
<name>Services: Unbound DNS: Edit Domain Override</name>
|
||||
<page-services-dnsresolver-overrides>
|
||||
<name>Services: Unbound DNS: Edit Host and Domain Override</name>
|
||||
<patterns>
|
||||
<pattern>services_unbound_overrides.php</pattern>
|
||||
<pattern>services_unbound_domainoverride_edit.php*</pattern>
|
||||
<pattern>ui/unbound/overrides/*</pattern>
|
||||
<pattern>api/unbound/overrides/*</pattern>
|
||||
</patterns>
|
||||
</page-services-dnsresolver-editdomainoverride>
|
||||
<page-services-dnsresolver-edithost>
|
||||
<name>Services: Unbound DNS: Edit Host Override</name>
|
||||
<patterns>
|
||||
<pattern>services_unbound_overrides.php</pattern>
|
||||
<pattern>services_unbound_host_edit.php*</pattern>
|
||||
</patterns>
|
||||
</page-services-dnsresolver-edithost>
|
||||
</page-services-dnsresolver-overrides>
|
||||
<page-diagnostics-logs-resolver>
|
||||
<name>Services: Unbound DNS: Log File</name>
|
||||
<patterns>
|
||||
|
||||
@ -2,10 +2,7 @@
|
||||
<Services>
|
||||
<Unbound VisibleName="Unbound DNS" cssClass="fa fa-tags fa-fw">
|
||||
<General order="10" url="/services_unbound.php"/>
|
||||
<Overrides order="20" url="/services_unbound_overrides.php">
|
||||
<Hosts url="/services_unbound_host_edit.php*" visibility="hidden"/>
|
||||
<Domains url="/services_unbound_domainoverride_edit.php*" visibility="hidden"/>
|
||||
</Overrides>
|
||||
<Overrides order="20" url="/ui/unbound/overrides/"/>
|
||||
<Advanced order="30" url="/services_unbound_advanced.php"/>
|
||||
<ACL VisibleName="Access Lists" order="40" url="/services_unbound_acls.php">
|
||||
<All url="/services_unbound_acls.php*" visibility="hidden"/>
|
||||
|
||||
108
src/opnsense/mvc/app/models/OPNsense/Unbound/Migrations/M1_0_1.php
Executable file
108
src/opnsense/mvc/app/models/OPNsense/Unbound/Migrations/M1_0_1.php
Executable file
@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2022 Deciso B.V.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
namespace OPNsense\Unbound\Migrations;
|
||||
|
||||
use OPNsense\Base\BaseModelMigration;
|
||||
use OPNsense\Base\FieldTypes\BooleanField;
|
||||
use OPNsense\Base\FieldTypes\NetworkField;
|
||||
use OPNsense\Base\FieldTypes\PortField;
|
||||
use OPNsense\Core\Config;
|
||||
|
||||
class M1_0_1 extends BaseModelMigration
|
||||
{
|
||||
/**
|
||||
* Migrate older models into shared model
|
||||
* @param $model
|
||||
*/
|
||||
public function run($model)
|
||||
{
|
||||
$config = Config::getInstance()->object();
|
||||
|
||||
if (!empty($config->unbound->hosts)) {
|
||||
foreach($config->unbound->hosts as $old_host) {
|
||||
$new_host = $model->hosts->host->add();
|
||||
|
||||
/* Backwards compatibility for records created before introducing RR types. */
|
||||
if (!isset($old_host->rr)) {
|
||||
$old_host->rr = (strpos($old_host->ip, ':') !== false) ? 'AAAA' : 'A';
|
||||
}
|
||||
|
||||
$host_data = [
|
||||
'enabled' => 1,
|
||||
'hostname' => !empty($old_host->host) ? $old_host->host : null,
|
||||
'domain' => $old_host->domain,
|
||||
'rr' => $old_host->rr,
|
||||
'server' => $old_host->rr == 'A' ? $old_host->ip : null,
|
||||
'mxprio' => $old_host->rr == 'MX' ? $old_host->mxprio : null,
|
||||
'mx' => $old_host->rr == 'MX' ? $old_host->mx : null,
|
||||
'description' => !empty($old_host->descr) ? $old_host->descr : null
|
||||
];
|
||||
|
||||
$new_host->setNodes($host_data);
|
||||
|
||||
$uuid = $new_host->getAttribute('uuid');
|
||||
foreach ($old_host->aliases->item as $old_alias) {
|
||||
if (!empty($old_alias)) {
|
||||
$new_alias = $model->aliases->alias->add();
|
||||
$alias_data = [
|
||||
'enabled' => 1,
|
||||
'host' => $uuid,
|
||||
'domain' => $old_alias->domain,
|
||||
'hostname' => !empty($old_alias->host) ? $old_alias->host : null
|
||||
];
|
||||
$new_alias->setNodes($alias_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($config->unbound->domainoverrides)) {
|
||||
foreach($config->unbound->domainoverrides as $old_domain) {
|
||||
$new_domain = $model->domains->domain->add();
|
||||
$domain_data = [
|
||||
'enabled' => 1,
|
||||
'domain' => $old_domain->domain,
|
||||
'server' => $old_domain->ip,
|
||||
'description' => !empty($old_domain->descr) ? $old_domain->descr : null
|
||||
];
|
||||
$new_domain->setNodes($domain_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup old config after config save
|
||||
* @param $model
|
||||
*/
|
||||
public function post($model)
|
||||
{
|
||||
$cfgObj = Config::getInstance()->object();
|
||||
unset($cfgObj->unbound->hosts, $cfgObj->unbound->domainoverrides);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
<model>
|
||||
<mount>//OPNsense/unboundplus</mount>
|
||||
<description>Unbound configuration</description>
|
||||
<version>1.0.0</version>
|
||||
<version>1.0.1</version>
|
||||
<items>
|
||||
<service_enabled type="LegacyLinkField">
|
||||
<Source>unbound.enable</Source>
|
||||
@ -73,6 +73,128 @@
|
||||
</verify>
|
||||
</dot>
|
||||
</dots>
|
||||
<hosts>
|
||||
<host type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<hostname type="HostnameField">
|
||||
<Required>N</Required>
|
||||
<WildcardAllowed>Y</WildcardAllowed>
|
||||
</hostname>
|
||||
<domain type="TextField">
|
||||
<Required>Y</Required>
|
||||
<mask>/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i</mask>
|
||||
<ValidationMessage>A valid domain must be specified.</ValidationMessage>
|
||||
</domain>
|
||||
<rr type="OptionField">
|
||||
<Required>Y</Required>
|
||||
<default>A</default>
|
||||
<OptionValues>
|
||||
<A>A or AAAA (IPv4 or IPv6 address)</A>
|
||||
<MX>MX (Mail server)</MX>
|
||||
</OptionValues>
|
||||
</rr>
|
||||
<mxprio type="IntegerField">
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>The field MX Priority is required.</ValidationMessage>
|
||||
<type>SetIfConstraint</type>
|
||||
<field>rr</field>
|
||||
<check>MX</check>
|
||||
</check001>
|
||||
</Constraints>
|
||||
</mxprio>
|
||||
<mx type="HostnameField">
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>The field MX Host is required.</ValidationMessage>
|
||||
<type>SetIfConstraint</type>
|
||||
<field>rr</field>
|
||||
<check>MX</check>
|
||||
</check001>
|
||||
</Constraints>
|
||||
</mx>
|
||||
<server type="NetworkField">
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>The field IP address is required.</ValidationMessage>
|
||||
<type>SetIfConstraint</type>
|
||||
<field>rr</field>
|
||||
<check>A</check>
|
||||
</check001>
|
||||
</Constraints>
|
||||
</server>
|
||||
<description type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.,_\x{00A0}-\x{FFFF}]){1,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</description>
|
||||
</host>
|
||||
</hosts>
|
||||
<aliases>
|
||||
<alias type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<host type="ModelRelationField">
|
||||
<Model>
|
||||
<host>
|
||||
<source>OPNsense.Unbound.Unbound</source>
|
||||
<items>hosts.host</items>
|
||||
<display>domain</display>
|
||||
</host>
|
||||
</Model>
|
||||
<Required>Y</Required>
|
||||
</host>
|
||||
<hostname type="HostnameField">
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>The host field is required if a domain has not been specified.</ValidationMessage>
|
||||
<type>SetIfConstraint</type>
|
||||
<field>domain</field>
|
||||
<check></check>
|
||||
</check001>
|
||||
</Constraints>
|
||||
<WildcardAllowed>Y</WildcardAllowed>
|
||||
</hostname>
|
||||
<domain type="TextField">
|
||||
<Constraints>
|
||||
<check001>
|
||||
<ValidationMessage>The domain field is required if a host has not been specified.</ValidationMessage>
|
||||
<type>SetIfConstraint</type>
|
||||
<field>hostname</field>
|
||||
<check></check>
|
||||
</check001>
|
||||
</Constraints>
|
||||
<mask>/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i</mask>
|
||||
<ValidationMessage>A valid domain must be specified.</ValidationMessage>
|
||||
</domain>
|
||||
</alias>
|
||||
</aliases>
|
||||
<domains>
|
||||
<domain type="ArrayField">
|
||||
<enabled type="BooleanField">
|
||||
<default>1</default>
|
||||
<Required>Y</Required>
|
||||
</enabled>
|
||||
<domain type="TextField">
|
||||
<Required>Y</Required>
|
||||
<mask>/^(?:(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])\.)*(?:[a-z0-9]|[a-z0-9][a-z0-9\-]*[a-z0-9])$/i</mask>
|
||||
<ValidationMessage>A valid domain must be specified.</ValidationMessage>
|
||||
</domain>
|
||||
<server type="NetworkField">
|
||||
<Required>Y</Required>
|
||||
</server>
|
||||
<description type="TextField">
|
||||
<Required>N</Required>
|
||||
<mask>/^([\t\n\v\f\r 0-9a-zA-Z.,_\x{00A0}-\x{FFFF}]){1,255}$/u</mask>
|
||||
<ValidationMessage>Description should be a string between 1 and 255 characters</ValidationMessage>
|
||||
</description>
|
||||
</domain>
|
||||
</domains>
|
||||
<miscellaneous>
|
||||
<privatedomain type="CSVListField">
|
||||
<Required>N</Required>
|
||||
|
||||
289
src/opnsense/mvc/app/views/OPNsense/Unbound/overrides.volt
Executable file
289
src/opnsense/mvc/app/views/OPNsense/Unbound/overrides.volt
Executable file
@ -0,0 +1,289 @@
|
||||
{#
|
||||
# Copyright (c) 2014-2022 Deciso B.V.
|
||||
# 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.
|
||||
#}
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
/**
|
||||
* load content on tab changes
|
||||
*/
|
||||
let heading_appended = false;
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
if (e.target.id == 'host_overrides_tab') {
|
||||
$("#grid-aliases-wrapper").show();
|
||||
$("#grid-hosts").bootgrid('destroy');
|
||||
let grid_hosts = $("#grid-hosts").UIBootgrid({
|
||||
search:'/api/unbound/settings/searchHostOverride/',
|
||||
get:'/api/unbound/settings/getHostOverride/',
|
||||
set:'/api/unbound/settings/setHostOverride/',
|
||||
add:'/api/unbound/settings/addHostOverride/',
|
||||
del:'/api/unbound/settings/delHostOverride/',
|
||||
toggle:'/api/unbound/settings/toggleHostOverride/',
|
||||
options: {
|
||||
selection: true,
|
||||
multiSelect: false,
|
||||
rowSelect: true,
|
||||
formatters: {
|
||||
"mxformatter": function (column, row) {
|
||||
/* Format the "Value" column so it shows either an MX host ("MX" type) or a raw IP address ("A" type) */
|
||||
if (row.mx.length > 0) {
|
||||
row.server = row.mx + ' (prio ' + row.mxprio + ')';
|
||||
}
|
||||
return row.server;
|
||||
},
|
||||
/* commands and rowtoggles added here since adding a custom formatter removes these by default for some reason */
|
||||
"commands": function (column, row) {
|
||||
return '<button type="button" class="btn btn-xs btn-default command-edit bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-pencil"></span></button> ' +
|
||||
'<button type="button" class="btn btn-xs btn-default command-copy bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-clone"></span></button>' +
|
||||
'<button type="button" class="btn btn-xs btn-default command-delete bootgrid-tooltip" data-row-id="' + row.uuid + '"><span class="fa fa-fw fa-trash-o"></span></button>';
|
||||
},
|
||||
"rowtoggle": function (column, row) {
|
||||
if (parseInt(row[column.id], 2) === 1) {
|
||||
return '<span style="cursor: pointer;" class="fa fa-fw fa-check-square-o command-toggle bootgrid-tooltip" data-value="1" data-row-id="' + row.uuid + '"></span>';
|
||||
} else {
|
||||
return '<span style="cursor: pointer;" class="fa fa-fw fa-square-o command-toggle bootgrid-tooltip" data-value="0" data-row-id="' + row.uuid + '"></span>';
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
}).on("selected.rs.jquery.bootgrid", function (e, rows) {
|
||||
$("#grid-aliases").bootgrid('reload');
|
||||
}).on("deselected.rs.jquery.bootgrid", function (e, rows) {
|
||||
$("#grid-aliases").bootgrid('reload');
|
||||
}).on("loaded.rs.jquery.bootgrid", function (e) {
|
||||
let ids = $("#grid-hosts").bootgrid("getCurrentRows");
|
||||
if (ids.length > 0) {
|
||||
$("#grid-hosts").bootgrid('select', [ids[0].uuid]);
|
||||
}
|
||||
|
||||
/* Hide/unhide input fields based on selected RR (Type) value */
|
||||
$('select[id="host.rr"]').on('change', function(e) {
|
||||
if (this.value == "A") {
|
||||
$('tr[id="row_host.mx"]').addClass('hidden');
|
||||
$('tr[id="row_host.mxprio"]').addClass('hidden');
|
||||
$('tr[id="row_host.server"]').removeClass('hidden');
|
||||
} else if (this.value == "MX") {
|
||||
$('tr[id="row_host.server"]').addClass('hidden');
|
||||
$('tr[id="row_host.mx"]').removeClass('hidden');
|
||||
$('tr[id="row_host.mxprio"]').removeClass('hidden');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
let grid_aliases = $("#grid-aliases").UIBootgrid({
|
||||
search:'/api/unbound/settings/searchHostAlias/',
|
||||
get:'/api/unbound/settings/getHostAlias/',
|
||||
set:'/api/unbound/settings/setHostAlias/',
|
||||
add:'/api/unbound/settings/addHostAlias/',
|
||||
del:'/api/unbound/settings/delHostAlias/',
|
||||
toggle:'/api/unbound/settings/toggleHostAlias/',
|
||||
options: {
|
||||
selection: true,
|
||||
multiSelect: true,
|
||||
rowSelect: true,
|
||||
useRequestHandlerOnGet: true,
|
||||
requestHandler: function(request) {
|
||||
let uuids = $("#grid-hosts").bootgrid("getSelectedRows");
|
||||
request['host'] = uuids.length > 0 ? uuids[0] : "__not_found__";
|
||||
let selected = $(".host_selected");
|
||||
uuids.length > 0 ? selected.show() : selected.hide();
|
||||
return request;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!heading_appended) {
|
||||
$("div.actionBar").each(function(){
|
||||
if ($(this).closest(".bootgrid-header").attr("id").includes("alias")) {
|
||||
$(this).parent().prepend($('<td id="heading-wrapper" class="col-sm-2 theading-text">{{ lang._('Aliases') }}</div>'));
|
||||
$(this).removeClass("col-sm-12");
|
||||
$(this).addClass("col-sm-10");
|
||||
heading_appended = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} else if (e.target.id == 'domain_overrides_tab') {
|
||||
$("#grid-aliases-wrapper").hide();
|
||||
$("#grid-domains").bootgrid('destroy');
|
||||
let grid_domains = $("#grid-domains").UIBootgrid({
|
||||
search:'/api/unbound/settings/searchDomainOverride/',
|
||||
get:'/api/unbound/settings/getDomainOverride/',
|
||||
set:'/api/unbound/settings/setDomainOverride/',
|
||||
add:'/api/unbound/settings/addDomainOverride/',
|
||||
del:'/api/unbound/settings/delDomainOverride/',
|
||||
toggle:'/api/unbound/settings/toggleDomainOverride/',
|
||||
options: {
|
||||
selection: true,
|
||||
multiSelect: true,
|
||||
rowSelect: true,
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (window.location.hash != "") {
|
||||
$('a[href="' + window.location.hash + '"]').click();
|
||||
} else {
|
||||
$('a[href="#host_overrides"]').click();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconfigure unbound - activate changes
|
||||
*/
|
||||
$("#reconfigureAct").SimpleActionButton();
|
||||
updateServiceControlUI('unbound');
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.theading-text {
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
#infosection {
|
||||
margin: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<ul class="nav nav-tabs" data-tabs="tabs" id="maintabs">
|
||||
<li><a data-toggle="tab" href="#host_overrides" id="host_overrides_tab">{{ lang._('Host Overrides') }}</a></li>
|
||||
<li><a data-toggle="tab" href="#domain_overrides" id="domain_overrides_tab">{{ lang._('Domain Overrides') }}</a></li>
|
||||
</ul>
|
||||
<div class="tab-content content-box col-xs-12 __mb">
|
||||
<!-- host overrides -->
|
||||
<div id="host_overrides" class="tab-pane fade in active">
|
||||
<table id="grid-hosts" class="table table-condensed table-hover table-striped" data-editDialog="DialogHostOverride" data-editAlert="OverrideChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="enabled" data-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="hostname" data-type="string">{{ lang._('Host') }}</th>
|
||||
<th data-column-id="domain" data-type="string">{{ lang._('Domain') }}</th>
|
||||
<th data-column-id="rr" data-type="string">{{ lang._('Type') }}</th>
|
||||
<th data-column-id="server" data-type="string" data-formatter="mxformatter">{{ lang._('Value') }}</th>
|
||||
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Edit') }} | {{ lang._('Delete') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button id="test" data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-fw fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div id="infosection" class="tab-content col-xs-12 __mb">
|
||||
{{ lang._('Entries in this section override individual results from the forwarders.') }}
|
||||
{{ lang._('Use these for changing DNS results or for adding custom DNS records.') }}
|
||||
{{ lang._('Keep in mind that all resource record types (i.e. A, AAAA, MX, etc. records) of a specified host below are being overwritten.') }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- domain overrides -->
|
||||
<div id="domain_overrides" class="tab-pane fade in">
|
||||
<table id="grid-domains" class="table table-condensed table-hover table-striped table-responsive" data-editDialog="DialogDomainOverride" data-editAlert="OverrideChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="enabled" data-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="domain" data-type="string">{{ lang._('Domain') }}</th>
|
||||
<th data-column-id="server" data-type="string">{{ lang._('IP') }}</th>
|
||||
<th data-column-id="description" data-type="string">{{ lang._('Description') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Edit') }} | {{ lang._('Delete') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-fw fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-fw fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div id="infosection" class="tab-content col-xs-12 __mb">
|
||||
{{ lang._('Entries in this area override an entire domain by specifying an authoritative DNS server to be queried for that domain.') }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- aliases for host overrides -->
|
||||
<div class="tab-content content-box col-xs-12 __mb" id ="grid-aliases-wrapper">
|
||||
<table id="grid-aliases" class="table table-condensed table-hover table-striped" data-editDialog="DialogHostAlias" data-editAlert="OverrideChangeMessage">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-column-id="uuid" data-type="string" data-identifier="true" data-visible="false">{{ lang._('ID') }}</th>
|
||||
<th data-column-id="enabled" data-width="6em" data-type="string" data-formatter="rowtoggle">{{ lang._('Enabled') }}</th>
|
||||
<th data-column-id="hostname" data-type="string">{{ lang._('Host') }}</th>
|
||||
<th data-column-id="domain" data-type="string">{{ lang._('Domain') }}</th>
|
||||
<th data-column-id="commands" data-width="7em" data-formatter="commands" data-sortable="false">{{ lang._('Commands') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
<tfoot class="host_selected">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<button data-action="add" type="button" class="btn btn-xs btn-primary"><span class="fa fa-fw fa-plus"></span></button>
|
||||
<button data-action="deleteSelected" type="button" class="btn btn-xs btn-default"><span class="fa fa-trash-o"></span></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<!-- reconfigure -->
|
||||
<div class="tab-content content-box col-xs-12 __mb">
|
||||
<div id="OverrideChangeMessage" class="alert alert-info" style="display: none" role="alert">
|
||||
{{ lang._('After changing settings, please remember to apply them with the button below') }}
|
||||
</div>
|
||||
<table class="table table-condensed">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<button class="btn btn-primary" id="reconfigureAct"
|
||||
data-endpoint='/api/unbound/service/reconfigure'
|
||||
data-label="{{ lang._('Apply') }}"
|
||||
data-service-widget="unbound"
|
||||
data-error-title="{{ lang._('Error reconfiguring unbound') }}"
|
||||
type="button"
|
||||
></button>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogHostOverride,'id':'DialogHostOverride','label':lang._('Edit Host Override')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogHostAlias,'id':'DialogHostAlias','label':lang._('Edit Host Override Alias')])}}
|
||||
{{ partial("layout_partials/base_dialog",['fields':formDialogDomainOverride,'id':'DialogDomainOverride','label':lang._('Edit Domain Override')])}}
|
||||
@ -33,7 +33,6 @@ import glob
|
||||
import collections
|
||||
import netaddr
|
||||
|
||||
|
||||
class SortKeyHelper:
|
||||
""" generate item key for sort function
|
||||
"""
|
||||
|
||||
@ -69,6 +69,9 @@ class Template(object):
|
||||
self._j2_env.filters['shlex_split'] = shlex.split
|
||||
self._j2_env.filters['regex_replace'] = lambda value, pattern, replacement: re.sub(pattern, replacement, value)
|
||||
|
||||
# register additional tests
|
||||
self._j2_env.tests['regex_match'] = lambda value, pattern: bool(re.match(pattern, value))
|
||||
|
||||
@staticmethod
|
||||
def _encode_idna(x):
|
||||
""" encode string to idna, preserve leading dots
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
blocklists.conf:/tmp/unbound-blocklists.conf
|
||||
dot.conf:/usr/local/etc/unbound.opnsense.d/dot.conf
|
||||
private_domains.conf:/var/unbound/private_domains.conf
|
||||
domainoverrides.conf:/usr/local/etc/unbound.opnsense.d/domainoverrides.conf
|
||||
miscellaneous.conf:/usr/local/etc/unbound.opnsense.d/miscellaneous.conf
|
||||
root.min.hints:/var/unbound/root.hints
|
||||
unbound_dhcpd.conf:/usr/local/etc/unbound_dhcpd.conf
|
||||
|
||||
17
src/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf
Executable file
17
src/opnsense/service/templates/OPNsense/Unbound/core/domainoverrides.conf
Executable file
@ -0,0 +1,17 @@
|
||||
{% if not helpers.empty('OPNsense.unboundplus.domains.domain') %}
|
||||
{% set forwardlocal = namespace(found=false) %}
|
||||
{% for domain in helpers.toList('OPNsense.unboundplus.domains.domain') %}
|
||||
{% if domain.enabled == '1' %}
|
||||
forward-zone:
|
||||
name: "{{ domain.domain }}"
|
||||
{% if domain.server.startswith('127.') or domain.server == '::1' %}
|
||||
{% set forwardlocal.found = true %}
|
||||
{% endif%}
|
||||
forward-addr: {{ domain.server }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% if forwardlocal.found %}
|
||||
server:
|
||||
do-not-query-localhost: no
|
||||
{% endif %}
|
||||
{% endif%}
|
||||
13
src/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf
Executable file
13
src/opnsense/service/templates/OPNsense/Unbound/core/private_domains.conf
Executable file
@ -0,0 +1,13 @@
|
||||
{% if not helpers.empty('OPNsense.unboundplus.domains.domain') %}
|
||||
# Set private domains in case authoritative name server returns a Private IP address
|
||||
{% for domain in helpers.toList('OPNsense.unboundplus.domains.domain') %}
|
||||
{% if domain.enabled == '1' %}
|
||||
domain-insecure: "{{ domain.domain }}"
|
||||
{% if domain.domain is regex_match('.+\.(in-addr|ip6)\.arpa\.?$') %}
|
||||
local-zone: {{ domain.domain }} typetransparent
|
||||
{% elif not helpers.exists('system.webgui.nodnsrebindcheck') %}
|
||||
private-domain: "{{ domain.domain }}"
|
||||
{% endif%}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
@ -1,166 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2014-2016 Deciso B.V.
|
||||
* Copyright (C) 2014 Warren Baker <warren@decoy.co.za>
|
||||
* Copyright (C) 2003-2005 Bob Zoller <bob@kludgebox.com>
|
||||
* Copyright (C) 2003-2005 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("guiconfig.inc");
|
||||
require_once("interfaces.inc");
|
||||
|
||||
$a_domainOverrides = &config_read_array('unbound', 'domainoverrides');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if (isset($_GET['id']) && !empty($a_domainOverrides[$_GET['id']])) {
|
||||
$id = $_GET['id'];
|
||||
}
|
||||
$pconfig = array();
|
||||
$pconfig['domain'] = isset($id) && !empty($a_domainOverrides[$id]['domain']) ? $a_domainOverrides[$id]['domain'] : null;
|
||||
$pconfig['ip'] = isset($id) && !empty($a_domainOverrides[$id]['ip']) ? $a_domainOverrides[$id]['ip'] : null;
|
||||
$pconfig['descr'] = isset($id) && !empty($a_domainOverrides[$id]['descr']) ? $a_domainOverrides[$id]['descr'] : null;
|
||||
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_GET['id']) && !empty($a_domainOverrides[$_POST['id']])) {
|
||||
$id = $_POST['id'];
|
||||
}
|
||||
$input_errors= array();
|
||||
$pconfig = $_POST;
|
||||
|
||||
/* input validation */
|
||||
$reqdfields = explode(" ", "domain ip");
|
||||
$reqdfieldsn = array(gettext("Domain"),gettext("IP address"));
|
||||
|
||||
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
|
||||
if (!empty($pconfig['domain']) && substr($pconfig['domain'], 0, 6) == '_msdcs') {
|
||||
$subdomainstr = substr($pconfig['domain'], 7);
|
||||
if ($subdomainstr && !is_domain($subdomainstr)) {
|
||||
$input_errors[] = gettext("A valid domain must be specified after _msdcs.");
|
||||
}
|
||||
} elseif (!empty($pconfig['domain']) && !is_domain($_POST['domain'])) {
|
||||
$input_errors[] = gettext("A valid domain must be specified.");
|
||||
}
|
||||
|
||||
if (!empty($pconfig['ip'])) {
|
||||
if (strpos($pconfig['ip'],'@') !== false) {
|
||||
$ip_details = explode("@", $pconfig['ip']);
|
||||
if (!is_ipaddr($ip_details[0]) && !is_port($ip_details[1])) {
|
||||
$input_errors[] = gettext("A valid IP address and port must be specified, for example 192.168.100.10@5353.");
|
||||
}
|
||||
} elseif (!is_ipaddr($pconfig['ip'])) {
|
||||
$input_errors[] = gettext("A valid IP address must be specified, for example 192.168.100.10.");
|
||||
}
|
||||
}
|
||||
|
||||
if (count($input_errors) == 0) {
|
||||
$doment = array();
|
||||
$doment['domain'] = $pconfig['domain'];
|
||||
$doment['ip'] = $pconfig['ip'];
|
||||
$doment['descr'] = $pconfig['descr'];
|
||||
|
||||
if (isset($id)) {
|
||||
$a_domainOverrides[$id] = $doment;
|
||||
} else {
|
||||
$a_domainOverrides[] = $doment;
|
||||
}
|
||||
|
||||
mark_subsystem_dirty('unbound');
|
||||
write_config();
|
||||
header(url_safe('Location: /services_unbound_overrides.php'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$service_hook = 'unbound';
|
||||
legacy_html_escape_form_data($pconfig);
|
||||
include("head.inc");
|
||||
?>
|
||||
<body>
|
||||
<?php include("fbegin.inc"); ?>
|
||||
<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 style="width:22%"><strong><?=gettext("Edit Domain Override entry");?></strong></td>
|
||||
<td style="width:78%; text-align:right">
|
||||
<small><?=gettext("full help"); ?> </small>
|
||||
<i class="fa fa-toggle-off text-danger" style="cursor: pointer;" id="show_all_help_page"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_domain" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Domain");?></td>
|
||||
<td>
|
||||
<input name="domain" type="text" id="domain" size="40" value="<?=$pconfig['domain'];?>" />
|
||||
<div class="hidden" data-for="help_for_domain">
|
||||
<?=gettext("Domain to override (NOTE: this does not have to be a valid TLD!)"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em><?=gettext("test"); ?></em> <?=gettext("or"); ?> <em>mycompany.localdomain</em> <?=gettext("or"); ?> <em>1.168.192.in-addr.arpa</em>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_ip" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("IP address");?></td>
|
||||
<td>
|
||||
<input name="ip" type="text" id="ip" size="40" value="<?=$pconfig['ip'];?>" />
|
||||
<div class="hidden" data-for="help_for_ip">
|
||||
<?=gettext("IP address of the authoritative DNS server for this domain"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em>192.168.100.100</em><br />
|
||||
<?=gettext("To use a nondefault port for communication, append an '@' with the port number."); ?><br />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_descr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Description");?></td>
|
||||
<td>
|
||||
<input name="descr" type="text" id="descr" size="40" value="<?=$pconfig['descr'];?>" />
|
||||
<div class="hidden" data-for="help_for_descr">
|
||||
<?=gettext("You may enter a description here for your reference (not parsed).");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
<input name="Submit" type="submit" class="btn btn-primary" value="<?= html_safe(gettext('Save')) ?>" />
|
||||
<input type="button" class="btn btn-default" value="<?= html_safe(gettext('Cancel')) ?>" onclick="window.location.href='/services_unbound_overrides.php'" />
|
||||
<?php if (isset($id)): ?>
|
||||
<input name="id" type="hidden" value="<?=htmlspecialchars($id);?>" />
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php include("foot.inc"); ?>
|
||||
@ -1,377 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Manuel Faux <mfaux@conf.at>
|
||||
* Copyright (C) 2014-2016 Deciso B.V.
|
||||
* Copyright (C) 2014 Warren Baker <warren@decoy.co.za>
|
||||
* Copyright (C) 2003-2004 Bob Zoller <bob@kludgebox.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("guiconfig.inc");
|
||||
require_once("interfaces.inc");
|
||||
|
||||
$a_hosts = &config_read_array('unbound', 'hosts');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||
if (isset($_GET['id']) && !empty($a_hosts[$_GET['id']])) {
|
||||
$id = $_GET['id'];
|
||||
}
|
||||
$pconfig = array();
|
||||
foreach (array('rr', 'host', 'domain', 'ip', 'mxprio', 'mx', 'descr', 'aliases') as $fieldname) {
|
||||
if (isset($id) && !empty($a_hosts[$id][$fieldname])) {
|
||||
$pconfig[$fieldname] = $a_hosts[$id][$fieldname];
|
||||
} else {
|
||||
$pconfig[$fieldname] = null;
|
||||
}
|
||||
}
|
||||
} elseif ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['id']) && !empty($a_hosts[$_POST['id']])) {
|
||||
$id = $_POST['id'];
|
||||
}
|
||||
|
||||
$input_errors = array();
|
||||
$pconfig = $_POST;
|
||||
|
||||
$pconfig['aliases'] = array();
|
||||
if (isset($pconfig['aliases_host'])) {
|
||||
$pconfig['aliases']['item'] = array();
|
||||
foreach ($pconfig['aliases_host'] as $opt_seq => $opt_host) {
|
||||
if (empty($opt_host) && empty($pconfig['aliases_domain'][$opt_seq]) && empty($pconfig['aliases_descr'][$opt_seq])) {
|
||||
continue;
|
||||
}
|
||||
$pconfig['aliases']['item'][] = array(
|
||||
'domain' => $pconfig['aliases_domain'][$opt_seq],
|
||||
'descr' => $pconfig['aliases_descr'][$opt_seq],
|
||||
'host' => $opt_host,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$reqdfields = explode(" ", "domain rr");
|
||||
$reqdfieldsn = array(gettext("Domain"),gettext("Type"));
|
||||
|
||||
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
|
||||
|
||||
if (!empty($pconfig['host']) && !is_hostname($pconfig['host']) && $pconfig['host'] != '*') {
|
||||
$input_errors[] = gettext("The hostname can only contain the characters A-Z, 0-9 and '-'.");
|
||||
}
|
||||
|
||||
if (!empty($pconfig['domain']) && !is_domain($pconfig['domain'])) {
|
||||
$input_errors[] = gettext("A valid domain must be specified.");
|
||||
}
|
||||
|
||||
if (!empty($pconfig['domain']) && $pconfig['domain'] == $config['system']['domain'] && $pconfig['host'] == '*') {
|
||||
$input_errors[] = sprintf(
|
||||
gettext("A wildcard domain override is not supported for the local domain '%s'."),
|
||||
$config['system']['domain']
|
||||
);
|
||||
}
|
||||
|
||||
switch ($pconfig['rr']) {
|
||||
case 'A': /* also: AAAA */
|
||||
$reqdfields = explode(" ", "ip");
|
||||
$reqdfieldsn = array(gettext("IP address"));
|
||||
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
|
||||
|
||||
if (!empty($pconfig['ip']) && !is_ipaddr($pconfig['ip'])) {
|
||||
$input_errors[] = gettext("A valid IP address must be specified.");
|
||||
}
|
||||
break;
|
||||
case 'MX':
|
||||
$reqdfields = explode(" ", "mxprio mx");
|
||||
$reqdfieldsn = array(gettext("MX Priority"), gettext("MX Host"));
|
||||
do_input_validation($pconfig, $reqdfields, $reqdfieldsn, $input_errors);
|
||||
|
||||
if (!empty($pconfig['mxprio']) && !is_numericint($pconfig['mxprio'])) {
|
||||
$input_errors[] = gettext("A valid MX priority must be specified.");
|
||||
}
|
||||
|
||||
if (!empty($pconfig['mx']) && !is_domain($pconfig['mx'])) {
|
||||
$input_errors[] = gettext("A valid MX host must be specified.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$input_errors[] = gettext("A valid resource record type must be specified.");
|
||||
break;
|
||||
}
|
||||
|
||||
foreach ($pconfig['aliases']['item'] as $idx => $alias) {
|
||||
if (!empty($alias['host']) && !is_hostname($alias['host'])) {
|
||||
$input_errors[] = gettext('Hostnames in alias list can only contain the characters A-Z, 0-9 and \'-\'.');
|
||||
}
|
||||
if (!empty($alias['domain']) && !is_domain($alias['domain'])) {
|
||||
$input_errors[] = gettext('A valid domain must be specified in alias list.');
|
||||
}
|
||||
if (empty($alias['host']) && empty($alias['domain'])) {
|
||||
$input_errors[] = gettext('A valid hostname or domain must be specified in alias list.');
|
||||
}
|
||||
}
|
||||
|
||||
if (count($input_errors) == 0) {
|
||||
$hostent = array();
|
||||
$hostent['host'] = $pconfig['host'];
|
||||
$hostent['domain'] = $pconfig['domain'];
|
||||
/* distinguish between A and AAAA by parsing the passed IP address */
|
||||
$hostent['rr'] = ($pconfig['rr'] == 'A' && is_ipaddrv6($pconfig['ip'])) ? 'AAAA' : $pconfig['rr'];
|
||||
$hostent['ip'] = $pconfig['ip'];
|
||||
$hostent['mxprio'] = $pconfig['mxprio'];
|
||||
$hostent['mx'] = $pconfig['mx'];
|
||||
$hostent['descr'] = $pconfig['descr'];
|
||||
$hostent['aliases'] = $pconfig['aliases'];
|
||||
|
||||
if (isset($id)) {
|
||||
$a_hosts[$id] = $hostent;
|
||||
} else {
|
||||
$a_hosts[] = $hostent;
|
||||
}
|
||||
|
||||
usort($a_hosts, function ($a, $b) {
|
||||
return strcasecmp($a['host'], $b['host']);
|
||||
});
|
||||
|
||||
mark_subsystem_dirty('unbound');
|
||||
write_config();
|
||||
header(url_safe('Location: /services_unbound_overrides.php'));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
$service_hook = 'unbound';
|
||||
legacy_html_escape_form_data($pconfig);
|
||||
include("head.inc");
|
||||
?>
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
$("#rr").change(function() {
|
||||
$(".a_aaa_rec").hide();
|
||||
$(".mx_rec").hide();
|
||||
switch ($(this).val()) {
|
||||
case 'A':
|
||||
$('#ip').prop('disabled', false);
|
||||
$('#mxprio').prop('disabled', true);
|
||||
$('#mx').prop('disabled', true);
|
||||
$(".a_aaa_rec").show();
|
||||
break;
|
||||
case 'MX':
|
||||
$('#ip').prop('disabled', true);
|
||||
$('#mxprio').prop('disabled', false);
|
||||
$('#mx').prop('disabled', false);
|
||||
$(".mx_rec").show();
|
||||
break;
|
||||
}
|
||||
$( window ).resize(); // call window resize, which will re-apply zebra
|
||||
});
|
||||
// trigger initial change
|
||||
$("#rr").change();
|
||||
|
||||
/**
|
||||
* Aliases
|
||||
*/
|
||||
function removeRow() {
|
||||
if ( $('#aliases_table > tbody > tr').length == 1 ) {
|
||||
$('#aliases_table > tbody > tr:last > td > input').each(function(){
|
||||
$(this).val("");
|
||||
});
|
||||
} else {
|
||||
$(this).parent().parent().remove();
|
||||
}
|
||||
}
|
||||
// add new detail record
|
||||
$("#addNew").click(function(){
|
||||
// copy last row and reset values
|
||||
$('#aliases_table > tbody').append('<tr>'+$('#aliases_table > tbody > tr:last').html()+'</tr>');
|
||||
$('#aliases_table > tbody > tr:last > td > input').each(function(){
|
||||
$(this).val("");
|
||||
});
|
||||
$(".act-removerow").click(removeRow);
|
||||
});
|
||||
$(".act-removerow").click(removeRow);
|
||||
});
|
||||
</script>
|
||||
<body>
|
||||
<?php include("fbegin.inc"); ?>
|
||||
<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 style="width:22%"><strong><?= gettext('Edit entry') ?></strong></td>
|
||||
<td style="width:78%; text-align:right">
|
||||
<small><?=gettext("full help"); ?> </small>
|
||||
<i class="fa fa-toggle-off text-danger" style="cursor: pointer;" id="show_all_help_page"></i>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_host" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Host");?></td>
|
||||
<td>
|
||||
<input name="host" type="text" value="<?=$pconfig['host'];?>" />
|
||||
<div class="hidden" data-for="help_for_host">
|
||||
<?= gettext('Name of the host, without domain part. Use "*" to create a wildcard entry.') ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_domain" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Domain");?></td>
|
||||
<td>
|
||||
<input name="domain" type="text" value="<?=$pconfig['domain'];?>" />
|
||||
<div class="hidden" data-for="help_for_domain">
|
||||
<?=gettext("Domain of the host"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em><?=gettext("example.com"); ?></em>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_rr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Type");?></td>
|
||||
<td>
|
||||
<select name="rr" id="rr" class="selectpicker">
|
||||
<?php
|
||||
$rrs = array("A" => gettext("A or AAAA (IPv4 or IPv6 address)"), "MX" => gettext("MX (Mail server)"));
|
||||
foreach ($rrs as $rr => $name) :?>
|
||||
<option value="<?=$rr;?>" <?=($rr == $pconfig['rr'] || ($rr == 'A' && $pconfig['rr'] == 'AAAA')) ? 'selected="selected"' : '';?> >
|
||||
<?=$name;?>
|
||||
</option>
|
||||
<?php
|
||||
endforeach; ?>
|
||||
</select>
|
||||
<div class="hidden" data-for="help_for_rr">
|
||||
<?=gettext("Type of resource record"); ?>
|
||||
<br />
|
||||
<?=gettext("e.g."); ?> <em>A</em> <?=gettext("or"); ?> <em>AAAA</em> <?=gettext("for IPv4 or IPv6 addresses"); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="a_aaa_rec">
|
||||
<td><a id="help_for_ip" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("IP");?></td>
|
||||
<td>
|
||||
<input name="ip" type="text" id="ip" value="<?=$pconfig['ip'];?>" />
|
||||
<div class="hidden" data-for="help_for_ip">
|
||||
<?=gettext("IP address of the host"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em>192.168.100.100</em> <?=gettext("or"); ?> <em>fd00:abcd::1</em>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mx_rec">
|
||||
<td><a id="help_for_mxprio" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("MX Priority");?></td>
|
||||
<td>
|
||||
<input name="mxprio" type="text" id="mxprio" value="<?=$pconfig['mxprio'];?>" />
|
||||
<div class="hidden" data-for="help_for_mxprio">
|
||||
<?=gettext("Priority of MX record"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em>10</em>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="mx_rec">
|
||||
<td><a id="help_for_mx" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("MX Host");?></td>
|
||||
<td>
|
||||
<input name="mx" type="text" id="mx" size="6" value="<?=$pconfig['mx'];?>" />
|
||||
<div class="hidden" data-for="help_for_mx">
|
||||
<?=gettext("Host name of MX host"); ?><br />
|
||||
<?=gettext("e.g."); ?> <em>mail.example.com</em>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_descr" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Description");?></td>
|
||||
<td>
|
||||
<input name="descr" type="text" id="descr" value="<?=$pconfig['descr'];?>" />
|
||||
<div class="hidden" data-for="help_for_descr">
|
||||
<?=gettext("You may enter a description here for your reference (not parsed).");?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a id="help_for_alias" href="#" class="showhelp"><i class="fa fa-info-circle"></i></a> <?=gettext("Aliases"); ?></td>
|
||||
<td>
|
||||
<table class="table table-striped table-condensed" id="aliases_table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th id="detailsHeading1"><?=gettext("Host"); ?></th>
|
||||
<th id="detailsHeading3"><?=gettext("Domain"); ?></th>
|
||||
<th id="updatefreqHeader" ><?=gettext("Description");?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$aliases = !empty($pconfig['aliases']['item']) ? $pconfig['aliases']['item'] : array();
|
||||
$aliases[] = array('number' => null, 'value' => null, 'type' => null);
|
||||
|
||||
foreach($aliases as $item): ?>
|
||||
<tr>
|
||||
<td>
|
||||
<div style="cursor:pointer;" class="act-removerow btn btn-default btn-xs"><i class="fa fa-minus fa-fw"></i></div>
|
||||
</td>
|
||||
<td>
|
||||
<input name="aliases_host[]" type="text" value="<?=$item['host'];?>" />
|
||||
</td>
|
||||
<td>
|
||||
<input name="aliases_domain[]" type="text" value="<?=$item['domain'];?>" />
|
||||
</td>
|
||||
<td>
|
||||
<input name="aliases_descr[]" type="text" value="<?=$item['descr'];?>" />
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
endforeach;?>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<div id="addNew" style="cursor:pointer;" class="btn btn-default btn-xs"><i class="fa fa-plus fa-fw"></i></div>
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<div class="hidden" data-for="help_for_alias">
|
||||
<?=gettext("Enter additional names for this host."); ?>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
<input name="Submit" type="submit" class="btn btn-primary" value="<?= html_safe(gettext('Save')) ?>" />
|
||||
<input type="button" class="btn btn-default" value="<?= html_safe(gettext('Cancel')) ?>" onclick="window.location.href='/services_unbound_overrides.php'" />
|
||||
<?php if (isset($id)): ?>
|
||||
<input name="id" type="hidden" value="<?=$id;?>" />
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php include("foot.inc"); ?>
|
||||
@ -1,252 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015 Manuel Faux <mfaux@conf.at>
|
||||
* Copyright (C) 2014-2016 Deciso B.V.
|
||||
* Copyright (C) 2014 Warren Baker <warren@decoy.co.za>
|
||||
* 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("system.inc");
|
||||
require_once("interfaces.inc");
|
||||
require_once("plugins.inc.d/unbound.inc");
|
||||
|
||||
$a_hosts = &config_read_array('unbound', 'hosts');
|
||||
$a_domains = &config_read_array('unbound', 'domainoverrides');
|
||||
|
||||
/* Backwards compatibility for records created before introducing RR types. */
|
||||
foreach ($a_hosts as $i => $hostent) {
|
||||
if (!isset($hostent['rr'])) {
|
||||
$a_hosts[$i]['rr'] = is_ipaddrv6($hostent['ip']) ? 'AAAA' : 'A';
|
||||
}
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$pconfig = $_POST;
|
||||
if (!empty($pconfig['apply'])) {
|
||||
unbound_configure_do();
|
||||
clear_subsystem_dirty('unbound');
|
||||
header(url_safe('Location: /services_unbound_overrides.php'));
|
||||
exit;
|
||||
} elseif (!empty($pconfig['act']) && $pconfig['act'] == 'del') {
|
||||
if (isset($pconfig['id']) && !empty($a_hosts[$pconfig['id']])) {
|
||||
unset($a_hosts[$pconfig['id']]);
|
||||
write_config();
|
||||
mark_subsystem_dirty('unbound');
|
||||
exit;
|
||||
}
|
||||
} elseif (!empty($pconfig['act']) && $pconfig['act'] == 'doverride') {
|
||||
if (isset($pconfig['id']) && !empty($a_domains[$pconfig['id']])) {
|
||||
unset($a_domains[$pconfig['id']]);
|
||||
write_config();
|
||||
mark_subsystem_dirty('unbound');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$service_hook = 'unbound';
|
||||
|
||||
legacy_html_escape_form_data($a_hosts);
|
||||
legacy_html_escape_form_data($a_domains);
|
||||
|
||||
include_once("head.inc");
|
||||
|
||||
?>
|
||||
<body>
|
||||
|
||||
<script>
|
||||
$( document ).ready(function() {
|
||||
// delete host action
|
||||
$(".act_delete_host").click(function(event){
|
||||
event.preventDefault();
|
||||
var id = $(this).data("id");
|
||||
// delete single
|
||||
BootstrapDialog.show({
|
||||
type:BootstrapDialog.TYPE_DANGER,
|
||||
title: "<?= gettext('Unbound') ?>",
|
||||
message: "<?=gettext("Do you really want to delete this host?");?>",
|
||||
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();
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
$(".act_delete_override").click(function(event){
|
||||
event.preventDefault();
|
||||
var id = $(this).data("id");
|
||||
// delete single
|
||||
BootstrapDialog.show({
|
||||
type:BootstrapDialog.TYPE_DANGER,
|
||||
title: "<?= gettext('Unbound') ?>",
|
||||
message: "<?=gettext("Do you really want to delete this domain override?");?>",
|
||||
buttons: [{
|
||||
label: "<?= gettext("No");?>",
|
||||
action: function(dialogRef) {
|
||||
dialogRef.close();
|
||||
}}, {
|
||||
label: "<?= gettext("Yes");?>",
|
||||
action: function(dialogRef) {
|
||||
$.post(window.location, {act: 'doverride', id:id}, function(data) {
|
||||
location.reload();
|
||||
});
|
||||
}
|
||||
}]
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php include("fbegin.inc"); ?>
|
||||
<section class="page-content-main">
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<?php if (is_subsystem_dirty('unbound')): ?>
|
||||
<?php print_info_box_apply(gettext('The Unbound configuration has been changed.') . ' ' . gettext('You must apply the changes in order for them to take effect.')) ?>
|
||||
<?php endif; ?>
|
||||
<form method="post" name="iform" id="iform">
|
||||
<section class="col-xs-12">
|
||||
<div class="content-box">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="6"><strong><?= gettext('Host Overrides') ?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= gettext('Host') ?></strong></td>
|
||||
<td><strong><?= gettext('Domain') ?></strong></td>
|
||||
<td><strong><?= gettext('Type') ?></strong></td>
|
||||
<td><strong><?= gettext('Value') ?></strong></td>
|
||||
<td><strong><?= gettext('Description') ?></strong></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="services_unbound_host_edit.php" class="btn btn-primary btn-xs"><i class="fa fa-plus fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php foreach ($a_hosts as $i => $hostent): ?>
|
||||
<tr>
|
||||
<td><?=strtolower($hostent['host']);?></td>
|
||||
<td><?=strtolower($hostent['domain']);?></td>
|
||||
<td><?=strtoupper($hostent['rr']);?></td>
|
||||
<td>
|
||||
<?php
|
||||
/* Presentation of DNS value differs between chosen RR type. */
|
||||
switch ($hostent['rr']) {
|
||||
case 'A':
|
||||
case 'AAAA':
|
||||
print $hostent['ip'];
|
||||
break;
|
||||
case 'MX':
|
||||
print $hostent['mxprio'] . " " . $hostent['mx'];
|
||||
break;
|
||||
default:
|
||||
print ' ';
|
||||
break;
|
||||
}?>
|
||||
</td>
|
||||
<td><?=$hostent['descr'];?></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="services_unbound_host_edit.php?id=<?=$i;?>" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
|
||||
<a href="#" data-id="<?=$i;?>" class="act_delete_host btn btn-xs btn-default"><i class="fa fa-trash fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php if (isset($hostent['aliases']['item'])): ?>
|
||||
<?php foreach ($hostent['aliases']['item'] as $alias): ?>
|
||||
<tr>
|
||||
<td><?= strtolower(!empty($alias['host']) ? $alias['host'] : $hostent['host']) ?></td>
|
||||
<td><?= strtolower(!empty($alias['domain']) ? $alias['domain'] : $hostent['domain']) ?></td>
|
||||
<td><?=strtoupper($hostent['rr']);?></td>
|
||||
<td><?= gettext('Alias for');?> <?=$hostent['host'] ? htmlspecialchars($hostent['host'] . '.' . $hostent['domain']) : htmlspecialchars($hostent['domain']);?></td>
|
||||
<td><?= !empty($alias['descr']) ? $alias['descr'] : $hostent['descr'] ?></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="services_unbound_host_edit.php?id=<?=$i;?>" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
<?php endif ?>
|
||||
<?php endforeach ?>
|
||||
<tr>
|
||||
<td colspan="6">
|
||||
<?=gettext("Entries in this section override individual results from the forwarders.");?>
|
||||
<?=gettext("Use these for changing DNS results or for adding custom DNS records.");?>
|
||||
<?=gettext("Keep in mind that all resource record types (i.e. A, AAAA, MX, etc. records) of a specified host below are being overwritten.");?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="col-xs-12">
|
||||
<div class="content-box">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="4"><strong><?= gettext('Domain Overrides') ?></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong><?= gettext('Domain') ?></strong></td>
|
||||
<td><strong><?= gettext('IP') ?></strong></td>
|
||||
<td><strong><?= gettext('Description') ?></strong></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="services_unbound_domainoverride_edit.php" class="btn btn-primary btn-xs"><i class="fa fa-plus fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php foreach ($a_domains as $i => $doment): ?>
|
||||
<tr>
|
||||
<td><?= strtolower($doment['domain']) ?></td>
|
||||
<td><?= $doment['ip'] ?></td>
|
||||
<td><?= $doment['descr'] ?></td>
|
||||
<td class="text-nowrap">
|
||||
<a href="services_unbound_domainoverride_edit.php?id=<?=$i;?>" class="btn btn-default btn-xs"><i class="fa fa-pencil fa-fw"></i></a>
|
||||
<a href="#" data-id="<?=$i;?>" class="act_delete_override btn btn-xs btn-default"><i class="fa fa-trash fa-fw"></i></a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach ?>
|
||||
<tr>
|
||||
<td colspan="4">
|
||||
<?= gettext('Entries in this area override an entire domain by specifying an authoritative DNS server to be queried for that domain.') ?>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php include("foot.inc"); ?>
|
||||
Loading…
x
Reference in New Issue
Block a user