From f1d6b8a9d3c06f74e904959887cf043d09aff687 Mon Sep 17 00:00:00 2001 From: Dexter Morgan Date: Thu, 2 Jun 2011 20:51:50 +0000 Subject: Branch for updates --- dns_wizard/Bind.pm | 930 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 930 insertions(+) create mode 100644 dns_wizard/Bind.pm (limited to 'dns_wizard/Bind.pm') diff --git a/dns_wizard/Bind.pm b/dns_wizard/Bind.pm new file mode 100644 index 00000000..29e2d766 --- /dev/null +++ b/dns_wizard/Bind.pm @@ -0,0 +1,930 @@ +#!/usr/bin/perl -w +# +# version 0.4 +# Copyright (C) 2004 Mandrakesoft +# Author: Antoine Ginies +# +# 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, 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 MDK::Wizard::Bind; +use lib qw(/usr/lib/libDrakX); + +use strict; +use services; +use common; +use MDK::Wizard::Varspaceval; +use MDK::Wizard::Wizcommon; +use network::network; + +my $wiz = new MDK::Wizard::Wizcommon; +my $in = interactive->vnew; +my $SERIAL = chomp_(`date +20%y%m%d`); +my $HOSTNAME = $wiz->{net}->network_get("HOSTNAME"); +my $BIND_CHROOT = "/var/lib/named"; + +my $IPSERVER = $wiz->{net}->itf_get("IPADDR"); +my $sys_wizard_dns = "/etc/sysconfig/drak_dns_wiz"; +if (-f $sys_wizard_dns) { + our ($interface) = cat_($sys_wizard_dns) =~ /INTERFACE=(.*)/; + ($IPSERVER) = `/sbin/ip addr show dev $interface` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; +} else { + our $interface = "eth0"; + ($IPSERVER) = `/sbin/ip addr show dev $interface` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; +} + +my $DOMAINNAME = chomp_(`dnsdomainname`); +my $CLIENTIP = get_spe_ip("ipnor", $IPSERVER) . "."; +my $WDIR = "/tmp/dnstest"; +my $NAMED_DIR = $BIND_CHROOT . "/var/named"; +my $DNSKEY = ""; +my $SHORTHOSTNAME = chomp_(`hostname -s`); +my $TEXTINFO = "dns Wizard"; +my $REP_SAVE = "/tmp/bck"; +my $ZONE_DIR = $NAMED_DIR . "/zone"; +my $DATE = `date +%d-%m-20%y`; + +my $o = { + name => 'DNS Configuration Wizard', + var => { + IPOFFORWARDER => '', + ADDSEARCH => '', + DOMAINNAME => $DOMAINNAME, + SHORTHOSTNAME => $SHORTHOSTNAME, + IPMASTER => '', + CLIENTNAME => '', + CLIENTIP => $CLIENTIP, + }, + init => sub { + my ($err, $msg) = test_host_domain($SHORTHOSTNAME, $DOMAINNAME); + if (!$err) { + $in->ask_warn(N('Error'), $msg); + die 'wizcancel'; + } + ($err, $msg) + }, + needed_rpm => [ 'bind' ], + defaultimage => "/usr/share/mcc/themes/default/dns_server-mdk.png", + }; + +my %level = ( + 1 => N("Master DNS server"), + 2 => N("Slave DNS server"), + 3 => N("Add host in DNS"), + 4 => N("Remove host in DNS"), + ); + +my @list_hosts; + +sub list_hosts { + my $iprev = get_spe_ip('iprev', $IPSERVER); + my $db = "$ZONE_DIR/db.$iprev.hosts"; + #my $ipnor = get_spe_ip('iprev', $IPSERVER); +# push @list_hosts, ""; + foreach (cat_($db)) { + my ($h) = /\d{1,3}\tIN\tPTR\t(.*)/; + !$h or push @list_hosts,$h; + } + @list_hosts; +} + +$o->{pages} = { + welcome => { + name => N("DNS Master configuration wizard") . "\n\n" . N("DNS (Domain Name Server) is the service that maps an IP address of a machine with an internet host name.") . "\n\n" . N("This wizard will help you configuring the DNS services of your server. This configuration will provide a local DNS service for local computers names, with non-local requests forwarded to an outside DNS."), + no_back => 1, + pre => sub { + $o->{var}{wiz_level} ||= 1; + }, + post => sub { + if ($o->{var}{wiz_level} == 2) { + return 'slave' } + elsif ($o->{var}{wiz_level} == 1) { + return 'interface' } + elsif ($o->{var}{wiz_level} == 3) { + if (-f $sys_wizard_dns) { return 'addhost' } else { return 'error_notmaster' } } + elsif ($o->{var}{wiz_level} == 4) { + if (-f $sys_wizard_dns) { return 'removehost' } else { return 'error_notmaster' } } + }, + data => [ + { label => '', val => \$o->{var}{wiz_level}, type => 'list', list => [ sort keys %level ], format => sub { $level{$_[0]} } }, + ], + next => 'interface', + }, + interface => { + name => N("DNS server Interface"), + data => [ + { list => [ keys %{$wiz->{net}{itf}} ], val => \$o->{var}{interface} }, + ], + no_back => 1, + next => 'ipforward' + }, + addhost => { + name => N("Client identification:") . "\n\n" . N("Your client on the network will be identified by name, as in clientname.company.net. Every machine on the network must have a (unique) IP address, in the usual dotted syntax.") . "\n\n" . N("(You don't need to add the domain after the name)") . "\n\n" . N("Note that the given IP address and client name should be unique in the network."), + data => [ + { label => N("Server:"), val_ref => \$o->{var}{SHORTHOSTNAME} }, + { label => N("DNS Domainname:"), val_ref => \$o->{var}{DOMAINNAME} }, + { label => N("Name of the machine:"), val => \$o->{var}{CLIENTNAME} }, + { label => N("IP address of the machine:"), val => \$o->{var}{CLIENTIP} }, + ], + complete => sub { + if ($o->{var}{CLIENTIP}) { + if (!is_ip($o->{var}{CLIENTIP})) { + #$in->ask_warn(N('Error'), N('This is not a valid IP address.')); + return 1; + } else { return 0; } + } + }, + no_back => 1, + next => 'summaryadd', no_back => 1, + }, + removehost => { + name => N("Remove host:") . "\n\n" . N("Remove a host in existing DNS configuration.") . "\n\n" . N("Choose the host you want to remove in the following list."), + data => [ + { label => N("Computer Name:"), val => \$o->{var}{CLIENTNAME}, list_ref => \@list_hosts }, + ], + post => \&list_hosts, + next => 'summaryremove', no_back => 1, + }, + slave => { + name => N("Slave DNS server") . "\n\n" . N("A slave name server will take some of the burden away from your primary name server, and will also function as a backup server, in case your master server is unreachable."), + data => [ + { label => N("IP Address of the master DNS server:"), val => \$o->{var}{IPMASTER} }, + ], + complete => sub { + if ($o->{var}{IPMASTER}) { + if (!is_ip($o->{var}{IPMASTER})) { + #$in->ask_warn(N('Error'), N('This is not a valid IP address.')); + return 1; + } else { return 0; } + } + }, + no_back => 1, + next => 'summaryslave', + }, + + ipforward => { + name => N("IP of your forwarder") . "\n\n" . N("Forwarding occurs on only those queries for which the server is not authoritative and does not have the answer in its cache.") . "\n\n" . N("If you need it and know your IP forwarder enter IP address of it, if you dont know leave it blank"), + pre => sub { + ($IPSERVER) = `/sbin/ip addr show dev $o->{var}{interface}` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; + output($sys_wizard_dns, "INTERFACE=$o->{var}{interface}\n"); + }, + data => [ + { label => N("External DNS:"), val => \$o->{var}{IPOFFORWARDER} }, + ], + complete => sub { + if ($o->{var}{IPOFFORWARDER}) { + if (!is_ip($o->{var}{IPOFFORWARDER})) { + #$in->ask_warn(N('Error'), N('This is not a valid IP address for your forwarder.')); + return 1; + } else { return 0; } + } + }, + no_back => 1, + next => 'addsearch', + }, + addsearch => { + name => N("Add search domain") . "\n\n" . N("Search list for host-name lookup. The search list is normally determined from the local domain name; by default, it contains only the local domain name. This may be changed by listing the desired domain search path following the search keyword") . "\n\n" . N("Domainname of this server is automatically added, and you dont need to add it here."), + + data => [ + { label => N("Default domain name to search:"), val => \$o->{var}{ADDSEARCH} }, + ], + next => 'summary', + }, + error_ipf => { + name => N("This is not a valid IP address for your forwarder... press next to continue"), + ignore => 1, + next => 'ipforward', + }, + error_ipm => { + name => N("This is not a valid Master DNS IP address... press next to continue"), + ignore => 1, + next => 'slave', + }, + error_iph => { + name => N("This is not a valid IP address... press next to continue"), + ignore => 1, + next => 'addhost', + }, + dhcp_warning => { + name => N("Warning") . "\n\n" . N("You are in dhcp, server may not work with your configuration."), + ignore => 1, + next => 'client_id' + }, + error_add => { + name => N("Error.") . "\n\n" . N("It seems that host is already in your DNS configuration... press next to continue"), + ignore => 1, + next => 'addhost', + }, + error_remove => { + name => N("Error:") . "\n\n" . N("It seems that this is not present in your DNS configuration... press next to continue"), + ignore => 1, + next => 'removehost', + }, + error_nosrv => { + name => N("It seems that no DNS server has been set through wizard. Please run DNS wizard: Master DNS server."), + end => 1, + }, + error_notmaster => { + name => N("It seems that you are not a master DNS server, so I can't add/remove host."), + end => 1, + }, + summaryslave => { + name => N("Wizard will Now build your DNS slave configuration") . "\n\n" . N("with this configuration:"), + data => [ + { label => N("IP Address of the master DNS server:"), val_ref => \$o->{var}{IPMASTER} }, + ], + post => \&do_it_slave, + next => 'end', + }, + summaryadd => { + name => N("Client with this identification will be added to your DNS"), + data => [ + { label => N("Server:"), val_ref => \$o->{var}{SHORTHOSTNAME} }, + { label => N("DNS Domainname:"), val_ref => \$o->{var}{DOMAINNAME} }, + { label => N("Computer name:"), val_ref => \$o->{var}{CLIENTNAME} }, + { label => N("Computer IP address:"), val_ref => \$o->{var}{CLIENTIP} }, + ], + post => \&do_it_add, + }, + summaryremove => { + name => N("Client with this identification will be removed from your DNS"), + data => [ + { label => N("Computer name:"), val => \$o->{var}{CLIENTNAME}, list_ref => \@list_hosts }, + ], + post => \&do_it_remove, + next => 'endremove', + }, + summary => { + name => N("The DNS server is about to be configured with the following configuration"), + data => [ + { label => N("Server Hostname:"), val_ref => \$o->{var}{SHORTHOSTNAME} }, + { label => N("Domainname:"), val_ref => \$o->{var}{DOMAINNAME} }, + { label => N("External DNS:"), val_ref => \$o->{var}{IPOFFORWARDER} }, + { label => N("Default domain name to search:"), val_ref => \$o->{var}{ADDSEARCH} }, + ], + post => \&do_it_master, + next => 'end', + }, + endadd => { + name => N("Congratulations"), + data => [ { label => N("The wizard successfully added the host in your DNS.") } ], + no_back => 1, + end => 1, + }, + endremove => { + name => N("Congratulations"), + data => [ { label => N("The wizard successfully removed the host from your DNS.") } ], + no_back => 1, + end => 1, + }, + end => { + name => N("Congratulations"), + data => [ { label => N("The wizard successfully configured the DNS service of your server.") } ], + no_back => 1, + end => 1, + }, + error_end => { + name => N("Failed"), + data => [ { label => N("Please Relaunch drakwizard, and try to change some parameters.") } ], + no_back => 1, + end => 1, + }, + }; + +sub test_srv { + my $dir = $BIND_CHROOT . "/var/named/zone"; + -d $dir or return 'error_nosrv'; +} + +sub interface_to_ip { + my ($interface) = @_; + my ($ip) = `/sbin/ip addr show dev $interface` =~ /^\s*inet\s+(\d+\.\d+\.\d+\.\d+)/m; + $ip; +} + +sub crea_wdir { + if (-e $WDIR) { system("rm -rf $WDIR") } + mkdir_p($WDIR); +} + +sub resolv_ip { + my ($ip) = @_; + gethostbyaddr(Socket::inet_aton($ip), Socket::AF_INET()); +} + +sub resolv_name { + my ($name) = @_; + join(".", unpack "C4", (gethostbyname $name)[4]); +} + + +sub get_spe_ip { + # waiting iprev, ipnorm or ipend + my ($att, $ip) = @_; + my @o = split(/\./, $ip); + if ($att =~ /iprev/) { + my $iprev = $o[2] . "." . $o[1] . "." . $o[0]; + return $iprev; + } elsif ($att =~ /ipnor/) { + my $ipnor = $o[0] . "." . $o[1] . "." . $o[2]; + return $ipnor; + } elsif ($att =~ /ipend/) { + my $ipend = $o[3]; + return $ipend; + } +} + +sub increment_serial { + my ($iprev) = @_; + my ($SERIAL) = cat_("$ZONE_DIR/db.$DOMAINNAME.hosts") =~ m/\s+(.*?)\s+;\s+Serial/; + $SERIAL = chomp_($SERIAL+1); + substInFile { + s/\s+\d+\s+;\s+Serial/ $SERIAL ; Serial/; + } "$ZONE_DIR/db.$DOMAINNAME.hosts"; + + substInFile { + s/\s+\d+\s+;\s+Serial/ $SERIAL ; Serial/; + } "$ZONE_DIR/db.$iprev.hosts"; +} + + +sub crea_db_local { + output($WDIR . "/db.localhost", <{var}{IPOFFORWARDER} or append_to_file($WDIR . "/named.conf", "\tforwarders { $o->{var}{IPOFFORWARDER}; };\n"); + append_to_file($WDIR . "/named.conf", <> DiG 8.1 <<>> \@A.ROOT-SERVERS.NET. +; (1 server found) +;; res options: init recurs defnam dnsrch +;; got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 10 +;; flags: qr aa rd; QUERY: 1, ANSWER: 13, AUTHORITY: 0, ADDITIONAL: 13 +;; QUERY SECTION: +;; ., type = NS, class = IN + +;; ANSWER SECTION: +. 6D IN NS G.ROOT-SERVERS.NET. +. 6D IN NS J.ROOT-SERVERS.NET. +. 6D IN NS K.ROOT-SERVERS.NET. +. 6D IN NS L.ROOT-SERVERS.NET. +. 6D IN NS M.ROOT-SERVERS.NET. +. 6D IN NS A.ROOT-SERVERS.NET. +. 6D IN NS H.ROOT-SERVERS.NET. +. 6D IN NS B.ROOT-SERVERS.NET. +. 6D IN NS C.ROOT-SERVERS.NET. +. 6D IN NS D.ROOT-SERVERS.NET. +. 6D IN NS E.ROOT-SERVERS.NET. +. 6D IN NS I.ROOT-SERVERS.NET. +. 6D IN NS F.ROOT-SERVERS.NET. + +;; ADDITIONAL SECTION: +G.ROOT-SERVERS.NET. 5w6d16h IN A 192.112.36.4 +J.ROOT-SERVERS.NET. 5w6d16h IN A 198.41.0.10 +K.ROOT-SERVERS.NET. 5w6d16h IN A 193.0.14.129 +L.ROOT-SERVERS.NET. 5w6d16h IN A 198.32.64.12 +M.ROOT-SERVERS.NET. 5w6d16h IN A 202.12.27.33 +A.ROOT-SERVERS.NET. 5w6d16h IN A 198.41.0.4 +H.ROOT-SERVERS.NET. 5w6d16h IN A 128.63.2.53 +B.ROOT-SERVERS.NET. 5w6d16h IN A 128.9.0.107 +C.ROOT-SERVERS.NET. 5w6d16h IN A 192.33.4.12 +D.ROOT-SERVERS.NET. 5w6d16h IN A 128.8.10.90 +E.ROOT-SERVERS.NET. 5w6d16h IN A 192.203.230.10 +I.ROOT-SERVERS.NET. 5w6d16h IN A 192.36.148.17 +F.ROOT-SERVERS.NET. 5w6d16h IN A 192.5.5.241 +;; Total query time: 215 msec +;; FROM: roke.uio.no to SERVER: A.ROOT-SERVERS.NET. 198.41.0.4 +;; WHEN: Sun Feb 15 01:22:51 1998 +;; MSG SIZE sent: 17 rcvd: 436 +EOF +} +# end roots.hints + +# create ipreverse +sub crea_iprev { + my ($ip, $d) = @_; + my $iprev = get_spe_ip('iprev', $ip); + my $ipend = get_spe_ip('ipend', $ip); + output($WDIR . "/db." . $iprev . ".hosts", <{var}{IPMASTER} or return append_to_file($WDIR . "/resolv.conf", "nameserver $o->{var}{IPMASTER}\n"); + !$o->{var}{ADDSEARCH} or return append_to_file($WDIR . "/resolv.conf", "search $o->{var}{ADDSEARCH}\n"); + !$o->{var}{IPOFFORWARDER} or return append_to_file($WDIR . "/resolv.conf", "nameserver $o->{var}{IPOFFORWARDER}\n"); +} +# end set resolv.conf + +# set /etc/hosts +sub set_hosts { + my ($ip, $h) = @_; + if (!any { /$ip\s* $h/ } cat_($WDIR . "/hosts")) { + append_to_file($WDIR . "/hosts", <{var}{IPMASTER}; + $ip or return 'slave'; + my @fields = $ip =~ $ip_regexp or return 'error_ipm'; + every { 0 <= $_ && $_ <= 255 } @fields or return 'error_ipm'; +} + +sub check_ipf { + my $ip = $o->{var}{IPOFFORWARDER}; + $ip or return 'addsearch'; + my @fields = $ip =~ $ip_regexp or return 'error_ipf'; + every { 0 <= $_ && $_ <= 255 } @fields or return 'error_ipf'; +} + + +sub check_iph { + my $ip = $o->{var}{CLIENTIP}; + my @fields = $ip =~ $ip_regexp or return 'error_iph'; + every { 0 <= $_ && $_ <= 255 } @fields or return 'error_iph'; +} + +sub do_it { + $::testing and return; + #my ($st) = @_; + crea_wdir($WDIR); + # create files + crea_db_local(); + crea_127(); + crea_named_common(); + # set host configuration + if (-f $WDIR . '/hosts') { rm_rf($WDIR . '/hosts') } + set_hosts('127.0.0.1', 'localhost.localdomain localhost'); + set_hosts($IPSERVER, $HOSTNAME); +} + +sub end_it { + crea_hints(); + crea_rndc(); + # set configuration files on server + set_resolv(); + # check generated config file are good + check_config(); + # create backup + save_old_config(); + # copy in correct place + copy_good(); + # start or restart the service + if (services::is_service_running('named')) { + services::restart('named') + } else { + services::start('named') + } +} + +sub do_it_master { + return if $::testing; + my $in = 'interactive'->vnew('su', 'dns'); + check_starts_on_boot($in, 'named'); + my $w = $in->wait_message(N("Master DNS server"), N("Configuring your system as Master DNS server ...")); + output($sys_wizard_dns, "INTERFACE=$o->{var}{interface}\n"); + do_it(); + crea_iprev($IPSERVER, $DOMAINNAME); + crea_ipnorm($IPSERVER, $DOMAINNAME); + crea_named_master($IPSERVER, $DOMAINNAME); + end_it(); + undef $w; + check_started('named'); +} + +sub do_it_slave { + return if $::testing; + my $in = 'interactive'->vnew('su', 'dns'); + check_starts_on_boot($in, 'named'); + my $w = $in->wait_message(N("Slave DNS server"), N("Configuring your system as Slave DNS server ...")); + if (-f $sys_wizard_dns) { unlink $sys_wizard_dns } + do_it(); + rm_rf(glob("$NAMED_DIR/bak*")); + crea_named_slave($IPSERVER, $DOMAINNAME, $o->{var}{IPMASTER}); + end_it(); + undef $w; + check_started('named'); +} + +sub get_shortname { +# sure someone can find a better method to do that + my ($name) = @_; + my @DT = split(/\./, $DOMAINNAME); + my $NB = $#DT; + if (any { /$DOMAINNAME$/x } $name) { + my @shortname = split(/\./, $name); + splice(@shortname, -$NB); + my $shortn; + foreach (@shortname) { + $shortn or return $shortn = $_; + !$shortn or return $shortn . "." . $_; + } + } else { return $name } +} + +sub do_it_add { + return if $::testing; + test_srv(); + my $iprev = get_spe_ip('iprev', $IPSERVER); + my $ipend = get_spe_ip('ipend', $o->{var}{CLIENTIP}); + my $SNAME = get_shortname($o->{var}{CLIENTNAME}); + if (any { /$ipend\tIN/ } cat_("$ZONE_DIR/db.$iprev.hosts")) { + return 'error_add'; + } elsif (any { /$SNAME.$DOMAINNAME.$/ } cat_("$ZONE_DIR/db.$iprev.hosts")) { + return 'error_add'; + } else { + append_to_file("$ZONE_DIR/db.$DOMAINNAME.hosts", + "$SNAME.$DOMAINNAME.\tIN\tA\t$o->{var}{CLIENTIP}\n"); + append_to_file("$ZONE_DIR/db.$iprev.hosts", + "$ipend\tIN\tPTR\t$SNAME.$DOMAINNAME.\n"); + } + increment_serial($iprev); + system("service named reload"); + return 'endadd' +} + +sub do_it_remove { + return if $::testing; + test_srv(); + my $iprev = get_spe_ip('iprev', $IPSERVER); + my $NAME = $o->{var}{CLIENTNAME}; + substInFile { + s/^\b$NAME.\b.*//; + s/^\s*$//; + } "$ZONE_DIR/db.$DOMAINNAME.hosts"; + substInFile { + s/^\d+\tIN\tPTR\t$NAME.*//; + s/^\s*$//; + } "$ZONE_DIR/db.$iprev.hosts"; + increment_serial($iprev); + system("service named reload"); +} + + +#34 IN PTR xp2400.guibland.com. +sub do_it_list { + return if $::testing; + my $iprev = get_spe_ip('iprev', $IPSERVER); + my $db = "$ZONE_DIR/db.$iprev.hosts"; + #my $ipnor = get_spe_ip('ipnor', $IPSERVER); + my @hosts; my @ip; + foreach (cat_($db)) { + my ($ipend, $h) = /(\d{1,3})\tIN\tPTR\t(.*)/; + if (!$h) { push @hosts, $h; push @ip, $ipend } + } +} + + +sub new { + my ($class) = @_; + bless $o, $class; +} + +1; -- cgit v1.2.1