234 lines
6.9 KiB
Perl
Executable File
234 lines
6.9 KiB
Perl
Executable File
#!/usr/bin/perl -w
|
|
#----------------------------------------------------------------------
|
|
# copyright (C) 1999-2008 Mitel Networks Corporation
|
|
#
|
|
# 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, write to the Free Software
|
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
#
|
|
#----------------------------------------------------------------------
|
|
package esmith;
|
|
|
|
use strict;
|
|
use Errno;
|
|
use esmith::ConfigDB;
|
|
use esmith::DomainsDB;
|
|
use esmith::NetworksDB;
|
|
use esmith::util;
|
|
|
|
sub allow_networks_2access_cache;
|
|
sub delegate_domains_2DNS;
|
|
|
|
unless (-f "/var/service/dnscache/seed")
|
|
{
|
|
system(qw(/bin/dd
|
|
if=/dev/urandom
|
|
of=/var/service/dnscache/seed
|
|
bs=128 count=1)) == 0
|
|
or warn("Could not create seed file");
|
|
}
|
|
|
|
open(STDIN, "<./seed") or warn "Failed to redirect input from seed file: $!";
|
|
open(STDERR, ">&STDOUT") or warn "Failed to redirect stderr to stdout: $!";;
|
|
|
|
my $config = esmith::ConfigDB->open or die "Could not open config db.";
|
|
my $dnscache = $config->get('dnscache');
|
|
my $forwarders = $dnscache->prop("Forwarder") || "";
|
|
if ($dnscache->prop("Forwarder2"))
|
|
{
|
|
$forwarders .= "," . $dnscache->prop("Forwarder2");
|
|
}
|
|
|
|
unless ($dnscache)
|
|
{
|
|
die "dnscache not configured in configuration db\n";
|
|
}
|
|
|
|
my $localip = $config->get('LocalIP');
|
|
unless ($localip)
|
|
{
|
|
die "localip not configured in configuration db\n";
|
|
}
|
|
|
|
my $tinydns = $config->get('tinydns');
|
|
unless ($tinydns)
|
|
{
|
|
die "tinydns not configured in configuration db\n";
|
|
}
|
|
my $tinydns_ip = $tinydns->prop('ListenIP') || "127.0.0.1";
|
|
|
|
$ENV{FORWARDONLY} = '1';
|
|
$ENV{IP} = $dnscache->prop('ListenIP') || $localip->value;
|
|
$ENV{IPSEND} = $dnscache->prop('SendIP') || '0.0.0.0';
|
|
$ENV{CACHESIZE} = 200000;
|
|
$ENV{ROOT} = '/service/dnscache/root';
|
|
|
|
my $domains = esmith::DomainsDB->open or die "Could not open Domains db.";
|
|
my $nets = esmith::NetworksDB->open or die "Could not open Networks db.";
|
|
|
|
#------------------------------------------------------------
|
|
# Configure DNS cache access.
|
|
#------------------------------------------------------------
|
|
|
|
# allow my networks to access the nameserver cache
|
|
my @localnetworks = ();
|
|
my %reversenets = ();
|
|
|
|
foreach my $net ($nets->get_all_by_prop('type', 'network'))
|
|
{
|
|
my $mask = $net->prop('Mask');
|
|
my $key = $net->key;
|
|
my $systemlocalnetwork = $net->prop('SystemLocalNetwork') || 'no';
|
|
my $nameserver = $net->prop('NameServer');
|
|
if (defined $nameserver and $nameserver eq $ENV{IP})
|
|
{
|
|
warn("NameServer property for net $key ($nameserver) would create loop - ignoring\n");
|
|
$nameserver = undef;
|
|
}
|
|
$nameserver ||= ($systemlocalnetwork eq 'yes') ? $tinydns_ip : 'none';
|
|
my @all_network_prefixes = esmith::util::computeAllLocalNetworkPrefixes ($key, $mask);
|
|
push @localnetworks, @all_network_prefixes;
|
|
|
|
unless ($nameserver eq 'none')
|
|
{
|
|
foreach (@all_network_prefixes)
|
|
{
|
|
my @quads = split(/\./, $_);
|
|
my $reverse_zone = join('.', reverse @quads) . ".in-addr.arpa";
|
|
$reversenets{$reverse_zone} = $nameserver;
|
|
}
|
|
}
|
|
}
|
|
|
|
allow_networks_2access_cache(@localnetworks);
|
|
|
|
delegate_domains_2DNS(
|
|
%reversenets,
|
|
map { $_->key => ($_->prop('Nameservers') || $tinydns_ip) }
|
|
($domains->get_all_by_prop('type', 'domain'),
|
|
$domains->get_all_by_prop('type', 'domain-remote')
|
|
));
|
|
|
|
my $datalimit = $dnscache->prop('DataLimit') || 3000000;
|
|
|
|
# Ensure that forwarder instance is started
|
|
system("sv", "u", "/service/dnscache.forwarder");
|
|
|
|
# http://marc.theaimsgroup.com/?l=djbdns&m=104812086607532&w=2
|
|
$SIG{'PIPE'} = 'IGNORE';
|
|
exec("envuidgid", "dnscache", "softlimit", "-o250", "-d", "$datalimit",
|
|
"/usr/local/bin/dnscache")
|
|
or die "failed to execute envuidgid/softlimit/dnscache: $!";
|
|
# NOTREACHED
|
|
exit (1);
|
|
|
|
sub allow_networks_2access_cache
|
|
{
|
|
my %access = map { $_ => 1 } @_;
|
|
|
|
my $dir = '/var/service/dnscache/root/ip';
|
|
unless (-f "$dir/127.0.0")
|
|
{
|
|
open F,">$dir/127.0.0"
|
|
|| die "Cannot add access file for loopback network: $!\n";
|
|
close F;
|
|
}
|
|
|
|
opendir(ACCESS, $dir) or
|
|
die "Cannot read dnscache access directory: $!";
|
|
|
|
foreach my $aclfile (readdir (ACCESS))
|
|
{
|
|
next if "$aclfile" eq "127.0.0";
|
|
next if -d "$aclfile";
|
|
if (exists $access{$aclfile})
|
|
{
|
|
# Cross this one off the list so that we don't bother creating it
|
|
delete $access{$aclfile};
|
|
}
|
|
else
|
|
{
|
|
# We no longer need this entry
|
|
unlink "$dir/$aclfile" or
|
|
warn "Could not delete dnscache access file $dir/$aclfile: $!\n";
|
|
}
|
|
}
|
|
closedir(ACCESS);
|
|
|
|
foreach my $aclfile (keys %access)
|
|
{
|
|
link "$dir/127.0.0", "$dir/$aclfile" or
|
|
die "Cannot add network access for $dir/$aclfile: $!\n";
|
|
}
|
|
}
|
|
|
|
sub delegate_domains_2DNS
|
|
{
|
|
my %delegations = @_;
|
|
my $serversdir = '/var/service/dnscache/root/servers';
|
|
|
|
opendir(SERVERS, $serversdir) or
|
|
die "Cannot read dnscache servers directory: $!";
|
|
|
|
foreach my $delegatefile (readdir (SERVERS))
|
|
{
|
|
next if "$delegatefile" eq '@';
|
|
|
|
next if -d "$serversdir/$delegatefile";
|
|
|
|
unless (exists $delegations{$delegatefile})
|
|
{
|
|
# We no longer need this entry
|
|
unlink "$serversdir/$delegatefile" or
|
|
warn "Could not delete dnscache domain file $serversdir/$delegatefile: $!\n";
|
|
}
|
|
}
|
|
closedir(SERVERS);
|
|
|
|
foreach my $delegatefile (keys %delegations)
|
|
{
|
|
if (-l "$serversdir/$delegatefile")
|
|
{
|
|
# Legacy symlink - we use files now
|
|
unlink "$serversdir/$delegatefile" or
|
|
warn "Could not delete dnscache domain link $serversdir/$delegatefile: $!\n";
|
|
}
|
|
|
|
open DELEGATE, ">$serversdir/$delegatefile" or
|
|
die "Couldn't create $serversdir/$delegatefile\n";
|
|
|
|
for my $ns ( split /,/, $delegations{$delegatefile} )
|
|
{
|
|
if ($ns =~ /^localhost$/)
|
|
{
|
|
print DELEGATE $tinydns_ip . "\n";
|
|
}
|
|
elsif ($ns =~ /^corporate$/)
|
|
{
|
|
print DELEGATE join("\n", split /,/, $forwarders) . "\n";
|
|
}
|
|
elsif ($ns =~ /^internet$/)
|
|
{
|
|
unlink "$serversdir/$delegatefile" or
|
|
warn "Couldn't unlink $serversdir/$delegatefile\n"
|
|
}
|
|
else
|
|
{
|
|
print DELEGATE $ns . "\n";
|
|
}
|
|
}
|
|
|
|
close DELEGATE;
|
|
}
|
|
}
|