Skip to content

Commit

Permalink
Merge branch 'devel' of github.com:eu-evops/FreeBSD-ports into devel
Browse files Browse the repository at this point in the history
  • Loading branch information
sponte committed Sep 27, 2023
2 parents 1c59142 + ce6697a commit 8badd5e
Show file tree
Hide file tree
Showing 14 changed files with 2,687 additions and 6 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ Makefile.local
*.rej
*.orig
*.sw[p-z]
.vscode/
.vscode/
vendor/
31 changes: 26 additions & 5 deletions dns/pfSense-pkg-bind/files/usr/local/pkg/bind.inc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ if (!function_exists("filter_configure")) {
require_once("notices.inc");
require_once("xmlrpc_client.inc");

/* Bind9 configuration parsers required to update dynamic zones */
require_once('bind/lib/Bind9ZoneConfiguration.php');
require_once('bind/lib/Bind9ZoneConfigurationParser.php');
require_once('bind/lib/Bind9ZoneRecord.php');
require_once('bind/lib/Bind9ZoneRecordParser.php');
require_once('bind/lib/Bind9ZoneSOARecord.php');
require_once('bind/lib/Bind9ZoneSOARecordParser.php');

define('BIND_LOCALBASE', '/usr/local');
define('CHROOT_LOCALBASE', '/var/etc/named');

Expand Down Expand Up @@ -596,12 +604,25 @@ EOD;
$named_process = "/usr/local/sbin/named";
if ($zone_is_dynamic && is_process_running($named_process)) {
exec("{$rndc} freeze " . escapeshellarg($zonename) . " IN " . escapeshellarg($zoneview));
// TODO: diff frozen zone DB with pfSense's stored DB file
// and (optionally?) add dynamic records to customzonerecords
}

// Save zone configuration DB file
file_put_contents(CHROOT_LOCALBASE."/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB", $zone_conf);
$dynamicZoneParser = new Bind9ZoneConfigurationParser(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB");
$dynamicConfiguration = $dynamicZoneParser->parse($zonename);

// Save temp file
file_put_contents(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB.tmp", $zone_conf);

$pfSenseZoneParser = new Bind9ZoneConfigurationParser(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB.tmp");
$pfSenseConfiguration = $pfSenseZoneParser->parse($zonename);

$pfSenseConfiguration->merge($dynamicConfiguration);

// Save merged configuration
file_put_contents(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB", $pfSenseConfiguration->toString());
unlink(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB.tmp");
} else {
// Save zone configuration DB file
file_put_contents(CHROOT_LOCALBASE . "/etc/namedb/{$zonetype}/{$zoneview}/{$zonename}.DB", $zone_conf);
}

// Thaw frozen dynamic zone
if ($zone_is_dynamic && is_process_running($named_process)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

class Bind9ZoneConfiguration
{
public array $records = [];

public function toString()
{
$result = "";
$origin = "";
$ttl = 0;

$longestHost = 0;
$longestType = 0;
$longestData = 0;

foreach ($this->records as $record) {
if (strlen($record->host) > $longestHost) {
$longestHost = strlen($record->host);
}
if (strlen($record->type) > $longestType) {
$longestType = strlen($record->type);
}
if (strlen($record->data) > $longestData) {
$longestData = strlen($record->data);
}
}

foreach ($this->records as $record) {
if ($ttl != $record->ttl) {
$ttl = $record->ttl;
$result .= "\n\$TTL " . $record->ttl . "\n";
}

if ($origin != $record->origin) {
$origin = $record->origin;
$result .= "\n\$ORIGIN " . $record->origin . "\n";
}

$result .= $record->toString($longestHost, $longestType, $longestData) . " ; TTL " . str_pad($record->ttl, 6) . " ORIGIN " . $record->origin . " FQDN " . $record->getFqdn() . " PHOST " . $record->inheritedHost . " -- " . $record->line . "\n";
}
return $result;
}

public function merge(Bind9ZoneConfiguration $other)
{
foreach ($other->records as $record) {
if ($record->type == "SOA") continue;
if ($record->type == "NS") continue;

if ($this->hasRecord($record)) {
$this->updateRecord($record);
} else {
$this->records[] = $record;
}
}
}

private function hasRecord(Bind9ZoneRecord $other): bool
{
foreach ($this->records as $r) {
if ($r->getFqdn() == $other->getFqdn() && $r->type == $other->type) {
return true;
}
}
return false;
}

private function updateRecord(Bind9ZoneRecord $other)
{
foreach ($this->records as $r) {
if ($r->host == $other->host && $r->type == $other->type) {
$r->data = $other->data;
$r->ttl = $other->ttl;
break;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
<?php

if (!function_exists('str_starts_with')) {
function str_starts_with($haystack, $needle)
{
return strpos($haystack, $needle) === 0;
}
}

if (!function_exists('str_ends_with')) {
function str_ends_with($haystack, $needle)
{
return strpos($haystack, $needle) === strlen($haystack) - 1;
}
}

class Bind9ZoneConfigurationParser
{
private string $filePath;
public function __construct(string $filePath)
{
$this->filePath = $filePath;
}

public function parse(string $zoneName): Bind9ZoneConfiguration
{
$f = fopen($this->filePath, 'r');

$currentTTL = 0;
$currentOrigin = "";
$parsingSOA = false;

$soaParser = new Bind9ZoneSOARecordParser();
$recordParser = new Bind9ZoneRecordParser();
$bindConfiguration = new Bind9ZoneConfiguration();

$soaRecordText = "";
$currentHost = "";

if ($f) {
while (($line = fgets($f)) !== false) {
$line = trim($line);
$lineComment = null;
if (preg_match("/;/", $line)) {
$lineComment = preg_replace("/.*;\s*/", "", $line);
$line = preg_replace("/\s*;.*/", "", $line);
}
$isRecord = true;

if (strlen($line) == 0) continue;
if ($line[0] == ';') continue;

if (str_starts_with($line, '$TTL')) {
$isRecord = false;

$currentTTL = substr(preg_replace("/\s*;.*/", "", $line), 5);
}

if (str_starts_with($line, '$ORIGIN')) {
$isRecord = false;
$currentOrigin = substr($line, 8);
}

if (str_ends_with($line, '(')) {
$parsingSOA = true;
// $line = substr($line, 0, strlen($line) - 1);
}

if ($parsingSOA) {
$soaRecordText .= " " . $line;
}

if (str_ends_with($line, ')')) {
$isRecord = false;
$parsingSOA = false;

$soaRecord = $soaParser->parse(trim($soaRecordText));
$soaRecord->zoneName = $zoneName;
$soaRecord->origin = $currentOrigin;
$soaRecord->ttl = $currentTTL;
$bindConfiguration->records[] = $soaRecord;
$currentRecord = $soaRecord;
}

if ($isRecord && !$parsingSOA) {
if ($recordParser->canParse($line)) {
$record = $recordParser->parse($line);
$record->zoneName = $zoneName;
$record->origin = $currentOrigin;
$record->ttl = $currentTTL;

if (!$record->host) {
$record->inheritedHost = $currentHost;
}

if ($currentRecord && $record->host == "") {
$record->inheritedHost = $currentRecord->host;
}

$bindConfiguration->records[] = $record;
if ($record->host) {
$currentHost = $record->host;
}
}
}
}
}

fclose($f);

return $bindConfiguration;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

class Bind9ZoneRecord
{
public string $line;
public string $origin;
public string $ttl;
public string $type;
public string $host;
public string $inheritedHost = "";
public string $data;
public string $zoneName;

public function toString(int $hostPadding = 0, int $typePadding = 0, int $dataPadding = 0): string
{
$result = str_pad($this->host, $hostPadding) . " " . str_pad($this->type, $typePadding) . " " . str_pad($this->data, $dataPadding);
return $result;
}

public function getFqdn(): string
{
return $this->getResultingHost($this->host);
}

private function getResultingHost(string $host): string
{
// FQDN
if (strlen($host) > 1 && str_ends_with($host, ".")) {
return $host;
}

if ($host == ".") {
return $this->getResultingHost($this->origin);
}

if ($host == "" && $this->inheritedHost != "") {
return $this->getResultingHost($this->inheritedHost);
}

if ($host == "@") {
return $this->zoneName . ".";
}

if ($this->origin == ".") {
return $host . $this->origin;
}

return $host . "." . $this->origin;
}
}
Loading

0 comments on commit 8badd5e

Please sign in to comment.