209 lines
6.3 KiB
PHP
209 lines
6.3 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This file is part of the Froxlor project.
|
|
* Copyright (c) 2010 the Froxlor Team (see authors).
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, you can also view it online at
|
|
* https://files.froxlor.org/misc/COPYING.txt
|
|
*
|
|
* @copyright the authors
|
|
* @author Froxlor team <team@froxlor.org>
|
|
* @license https://files.froxlor.org/misc/COPYING.txt GPLv2
|
|
*/
|
|
|
|
namespace Froxlor\Cron\Dns;
|
|
|
|
use Froxlor\Dns\Dns;
|
|
use Froxlor\Dns\DnsZone;
|
|
use Froxlor\FroxlorLogger;
|
|
use Froxlor\Settings;
|
|
use PDO;
|
|
|
|
class PowerDNS extends DnsBase
|
|
{
|
|
|
|
public function writeConfigs()
|
|
{
|
|
// tell the world what we are doing
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 started - Refreshing DNS database');
|
|
|
|
$domains = $this->getDomainList();
|
|
|
|
// clean up
|
|
$this->clearZoneTables($domains);
|
|
|
|
if (empty($domains)) {
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'No domains found for nameserver-config, not creating any zones...');
|
|
} else {
|
|
foreach ($domains as $domain) {
|
|
if ($domain['is_child']) {
|
|
// domains that are subdomains to other main domains are handled by recursion within walkDomainList()
|
|
continue;
|
|
}
|
|
$this->walkDomainList($domain, $domains);
|
|
}
|
|
}
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'PowerDNS database updated');
|
|
$this->reloadDaemon();
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Task4 finished');
|
|
}
|
|
|
|
private function clearZoneTables($domains = null)
|
|
{
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'Cleaning dns zone entries from database');
|
|
|
|
$pdns_domains_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("SELECT `id`, `name` FROM `domains` WHERE `name` = :domain");
|
|
|
|
$del_rec_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `records` WHERE `domain_id` = :did");
|
|
$del_meta_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domainmetadata` WHERE `domain_id` = :did");
|
|
$del_dom_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("DELETE FROM `domains` WHERE `id` = :did");
|
|
|
|
foreach ($domains as $domain) {
|
|
$pdns_domains_stmt->execute([
|
|
'domain' => $domain['domain']
|
|
]);
|
|
$pdns_domain = $pdns_domains_stmt->fetch(PDO::FETCH_ASSOC);
|
|
|
|
if ($pdns_domain && !empty($pdns_domain['id'])) {
|
|
$del_rec_stmt->execute([
|
|
'did' => $pdns_domain['id']
|
|
]);
|
|
$del_meta_stmt->execute([
|
|
'did' => $pdns_domain['id']
|
|
]);
|
|
$del_dom_stmt->execute([
|
|
'did' => $pdns_domain['id']
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
private function walkDomainList($domain, $domains)
|
|
{
|
|
$zoneContent = '';
|
|
$subzones = [];
|
|
|
|
foreach ($domain['children'] as $child_domain_id) {
|
|
$subzones[] = $this->walkDomainList($domains[$child_domain_id], $domains);
|
|
}
|
|
|
|
if ($domain['zonefile'] == '') {
|
|
// check for system-hostname
|
|
$isFroxlorHostname = false;
|
|
if (isset($domain['froxlorhost']) && $domain['froxlorhost'] == 1) {
|
|
$isFroxlorHostname = true;
|
|
}
|
|
|
|
if (!$domain['is_child']) {
|
|
$zoneContent = Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname);
|
|
if (count($subzones)) {
|
|
foreach ($subzones as $subzone) {
|
|
$zoneContent->records[] = $subzone;
|
|
}
|
|
}
|
|
$pdnsDomId = $this->insertZone($zoneContent->origin, $zoneContent->serial);
|
|
$this->insertRecords($pdnsDomId, $zoneContent->records, $zoneContent->origin);
|
|
$this->insertAllowedTransfers($pdnsDomId);
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_INFO, 'DB entries stored for zone `' . $domain['domain'] . '`');
|
|
} else {
|
|
return Dns::createDomainZone(($domain['id'] == 'none') ? $domain : $domain['id'], $isFroxlorHostname, true);
|
|
}
|
|
} else {
|
|
$this->logger->logAction(FroxlorLogger::CRON_ACTION, LOG_ERR, 'Custom zonefiles are NOT supported when PowerDNS is selected as DNS daemon (triggered by: ' . $domain['domain'] . ')');
|
|
}
|
|
}
|
|
|
|
private function insertZone($domainname, $serial = 0)
|
|
{
|
|
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
|
|
INSERT INTO domains set `name` = :domainname, `notified_serial` = :serial, `type` = :type
|
|
");
|
|
$ins_stmt->execute([
|
|
'domainname' => $domainname,
|
|
'serial' => $serial,
|
|
'type' => strtoupper(Settings::Get('system.powerdns_mode'))
|
|
]);
|
|
$lastid = \Froxlor\Dns\PowerDNS::getDB()->lastInsertId();
|
|
return $lastid;
|
|
}
|
|
|
|
private function insertRecords($domainid = 0, $records = [], $origin = "")
|
|
{
|
|
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
|
|
INSERT INTO records set
|
|
`domain_id` = :did,
|
|
`name` = :rec,
|
|
`type` = :type,
|
|
`content` = :content,
|
|
`ttl` = :ttl,
|
|
`prio` = :prio,
|
|
`disabled` = '0'
|
|
");
|
|
|
|
foreach ($records as $record) {
|
|
if ($record instanceof DnsZone) {
|
|
$this->insertRecords($domainid, $record->records, $record->origin);
|
|
continue;
|
|
}
|
|
|
|
if ($record->record == '@') {
|
|
$_record = $origin;
|
|
} else {
|
|
$_record = $record->record . "." . $origin;
|
|
}
|
|
|
|
$ins_data = [
|
|
'did' => $domainid,
|
|
'rec' => $_record,
|
|
'type' => $record->type,
|
|
'content' => $record->content,
|
|
'ttl' => $record->ttl,
|
|
'prio' => $record->priority
|
|
];
|
|
$ins_stmt->execute($ins_data);
|
|
}
|
|
}
|
|
|
|
private function insertAllowedTransfers($domainid)
|
|
{
|
|
$ins_stmt = \Froxlor\Dns\PowerDNS::getDB()->prepare("
|
|
INSERT INTO domainmetadata set `domain_id` = :did, `kind` = 'ALLOW-AXFR-FROM', `content` = :value
|
|
");
|
|
|
|
$ins_data = [
|
|
'did' => $domainid
|
|
];
|
|
|
|
if (count($this->ns) > 0 || count($this->axfr) > 0) {
|
|
// put nameservers in allow-transfer
|
|
if (count($this->ns) > 0) {
|
|
foreach ($this->ns as $ns) {
|
|
foreach ($ns["ips"] as $ip) {
|
|
$ins_data['value'] = $ip;
|
|
$ins_stmt->execute($ins_data);
|
|
}
|
|
}
|
|
}
|
|
// AXFR server #100
|
|
if (count($this->axfr) > 0) {
|
|
foreach ($this->axfr as $axfrserver) {
|
|
$ins_data['value'] = $axfrserver;
|
|
$ins_stmt->execute($ins_data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|