mirror of
				https://github.com/xcat2/xcat-core.git
				synced 2025-11-03 21:02:34 +00:00 
			
		
		
		
	git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@6822 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
		
			
				
	
	
		
			1549 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1549 lines
		
	
	
		
			42 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/perl
 | 
						|
# IBM(c) 2007 EPL license http://www.eclipse.org/legal/epl-v10.html
 | 
						|
#This is ported forward from xCAT 1.3
 | 
						|
#TODO: A lot of stuff was handled by the script portion of makedns, notably:
 | 
						|
# db.cache
 | 
						|
# forwarders
 | 
						|
# chroot
 | 
						|
# dnsallowq
 | 
						|
# mucking with sysconfig
 | 
						|
package xCAT_plugin::bind;
 | 
						|
use strict;
 | 
						|
no strict "refs";    #This code is as yet still very broken...
 | 
						|
 | 
						|
#use warnings;
 | 
						|
use Sys::Hostname;
 | 
						|
use Cwd;
 | 
						|
use Getopt::Long;
 | 
						|
use xCAT::Table;
 | 
						|
use xCAT::MsgUtils;
 | 
						|
use Data::Dumper;
 | 
						|
 | 
						|
sub handled_commands
 | 
						|
{
 | 
						|
    return {"makedns" => "bind"};
 | 
						|
}
 | 
						|
 | 
						|
#NAME
 | 
						|
#
 | 
						|
#    h2n - Translate host table to name server file format
 | 
						|
#    $Date: 1999/08/08 17:17:56 $  $Revision: 8.2 $
 | 
						|
#
 | 
						|
#SYNOPSIS
 | 
						|
#
 | 
						|
#    h2n -d DOMAIN -n NET [options]
 | 
						|
 | 
						|
# Various defaults
 | 
						|
my $Host;
 | 
						|
my $doaliases       = 1;
 | 
						|
my $domx            = 1;
 | 
						|
my $dowks           = 0;
 | 
						|
my $dotxt           = 0;
 | 
						|
my $dontdodomains   = 0;
 | 
						|
my $Bootfile        = "/etc/named.conf";
 | 
						|
my $DBDir           = "/var/named/";
 | 
						|
my $Domain          = "";
 | 
						|
my $Hostfile        = "/etc/hosts";
 | 
						|
my $Commentfile     = "";
 | 
						|
my $Commentfileread = 0;
 | 
						|
my $User            = "root";
 | 
						|
my $RespHost        = "";
 | 
						|
my $RespUser        = "";
 | 
						|
my $DefSerial       = 1;
 | 
						|
my $DefRefresh      = 10800;
 | 
						|
my $DefRetry        = 3600;
 | 
						|
my $DefExpire       = 604800;
 | 
						|
my $DefTtl          = 86400;
 | 
						|
my $UseDefSOAValues = 0;
 | 
						|
my $DefMxWeight     = 10;
 | 
						|
my $Defsubnetmask   = "";
 | 
						|
my $ForceSerial     = -1;
 | 
						|
my $UseDateInSerial = 1;
 | 
						|
my $DateSerial      = 0;
 | 
						|
my $Version         = 8;
 | 
						|
my $request;
 | 
						|
my $callback;
 | 
						|
my @forwarders;
 | 
						|
 | 
						|
#Declarations to alleviate use strict, since the code doesn't seem to be structured well enough to avoid it for these cases
 | 
						|
my $Bootsecsaveaddr;
 | 
						|
my $Bootsecaddr;
 | 
						|
my @Networks;
 | 
						|
my @bootmsgs_v4;
 | 
						|
my @bootmsgs_v8;
 | 
						|
my @elimpats;
 | 
						|
my @cpats;
 | 
						|
my @makesoa;
 | 
						|
my $Domainfile;
 | 
						|
my %cpatrel;
 | 
						|
my @Servers;
 | 
						|
my $Serial;
 | 
						|
my $Refresh;
 | 
						|
my @Mx;
 | 
						|
my $Expire;
 | 
						|
my %Hosts;
 | 
						|
my %Comments;
 | 
						|
my $Domainpattern;
 | 
						|
my @Netpatterns;
 | 
						|
my $Ttl;
 | 
						|
my $Retry;
 | 
						|
my %Cnames;
 | 
						|
my %CommentRRs;
 | 
						|
my $soa_warned;
 | 
						|
my %Aliases;
 | 
						|
my %Netfiles;
 | 
						|
 | 
						|
sub process_request
 | 
						|
{
 | 
						|
    $request    = shift;
 | 
						|
    $callback   = shift;
 | 
						|
    %Netfiles   = ();
 | 
						|
    %Aliases    = ();
 | 
						|
    $soa_warned = 0;
 | 
						|
    my $canonical;
 | 
						|
    my $aliases;
 | 
						|
    %Comments    = ();
 | 
						|
    %CommentRRs  = ();
 | 
						|
    %Cnames      = ();
 | 
						|
    %Hosts       = ();
 | 
						|
    @Netpatterns = ();
 | 
						|
    $DBDir       = "/var/named/";
 | 
						|
 | 
						|
    unless (-d $DBDir)
 | 
						|
    {
 | 
						|
        $DBDir = "/var/lib/named/";
 | 
						|
    }
 | 
						|
 | 
						|
    # if both do not exist, make /var/named
 | 
						|
    unless (-d $DBDir)
 | 
						|
    {
 | 
						|
        $DBDir = "/var/named/";
 | 
						|
        my $cmd = "/bin/mkdir $DBDir";
 | 
						|
        my $outref = xCAT::Utils->runcmd("$cmd", 0);
 | 
						|
        if ($::RUNCMD_RC != 0)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Could not create $DBDir.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    $Host = hostname;
 | 
						|
    $Host =~ s/\..*//;
 | 
						|
    my $sitetab = xCAT::Table->new('site');
 | 
						|
    unless ($sitetab)
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "No site table found.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    my @args = ();
 | 
						|
    if ($request->{arg})
 | 
						|
    {
 | 
						|
        @args = @{$request->{arg}};
 | 
						|
        @ARGV = @{$request->{arg}};
 | 
						|
    }
 | 
						|
    &checkusageandversion($callback);
 | 
						|
 | 
						|
    (my $fent) = $sitetab->getAttribs({key => 'forwarders'}, 'value');
 | 
						|
    if ($fent and defined $fent->{value})
 | 
						|
    {
 | 
						|
        @forwarders = split /[,:;]/, $fent->{value};
 | 
						|
    }
 | 
						|
    unless (grep /^-d$/, @args)
 | 
						|
    {
 | 
						|
        (my $dent) = $sitetab->getAttribs({key => 'domain'}, 'value');
 | 
						|
        if ($dent and $dent->{value})
 | 
						|
        {
 | 
						|
            push @args, "-d";
 | 
						|
            $dent->{value} =~ s/\.$//;
 | 
						|
            push @args, $dent->{value};
 | 
						|
        }
 | 
						|
    }
 | 
						|
    unless (grep /^-s$/, @args)
 | 
						|
    {
 | 
						|
        push @args, "-s";
 | 
						|
        push @args, $Host;
 | 
						|
    }
 | 
						|
    unless (grep /^-n$/, @args)
 | 
						|
    {
 | 
						|
        my $nettab = xCAT::Table->new('networks');
 | 
						|
        unless ($nettab)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] =
 | 
						|
              "Unable to open networks table, has makenetworks been run?.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            return;
 | 
						|
        }
 | 
						|
        foreach (@{$nettab->getAllEntries()})
 | 
						|
        {
 | 
						|
            push @args, "-n";
 | 
						|
            push @args, $_->{net} . ":" . $_->{mask};
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    push(@bootmsgs_v4, "primary\t0.0.127.IN-ADDR.ARPA db.127.0.0\n");
 | 
						|
    push(@bootmsgs_v8,
 | 
						|
         qq|zone "0.0.127.IN-ADDR.ARPA" in {\n\ttype master;\n\tfile "db.127.0.0";\n\tnotify no;\n};\n\n|
 | 
						|
         );
 | 
						|
 | 
						|
    &PARSEARGS($callback, @args);
 | 
						|
    &FIXUP($callback);
 | 
						|
    unless (open(HOSTS, $Hostfile))
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "Unable to open $Hostfile\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        exit 1;
 | 
						|
    }
 | 
						|
    my $data;
 | 
						|
    my $comment;
 | 
						|
    my $addr;
 | 
						|
    my $names;
 | 
						|
  LINE: while (<HOSTS>)
 | 
						|
    {
 | 
						|
        next if /^[ \t]*#/;    # skip comment lines
 | 
						|
        next if /^$/;          # skip empty lines
 | 
						|
        chop;                  # remove the trailing newline
 | 
						|
        tr/A-Z/a-z/;           # translate to lower case
 | 
						|
 | 
						|
        ($data, $comment) = split('#',     $_,    2);
 | 
						|
        ($addr, $names)   = split(/[ 	]+/, $data, 2);
 | 
						|
        if ($names =~ /^[ \t]*$/)
 | 
						|
        {
 | 
						|
 | 
						|
            #$callback->({data=>["Bad line in hosts file ignored '$_'"]});
 | 
						|
            next LINE;
 | 
						|
        }
 | 
						|
        $addr =~ s/^[    ]*//;
 | 
						|
        $addr =~ s/[    ]*$//;
 | 
						|
        if ($addr !~ /^\d+\.\d+\.\d+\.\d+$/)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Ignoring $addr (not a valid IPv4 address).\n";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            next LINE;
 | 
						|
        }
 | 
						|
 | 
						|
        # Match -e args
 | 
						|
        my $netpat;
 | 
						|
        foreach $netpat (@elimpats)
 | 
						|
        {
 | 
						|
            next LINE if (/[.\s]$netpat/);
 | 
						|
        }
 | 
						|
 | 
						|
        # Process -c args
 | 
						|
        foreach $netpat (@cpats)
 | 
						|
        {
 | 
						|
            if (/\.$netpat/)
 | 
						|
            {
 | 
						|
                ($canonical, $aliases) = split(' ', $names, 2);
 | 
						|
                $canonical =~ s/\.$netpat//;
 | 
						|
                #If we feed in names with, say, underscores, bind complains usually due to default check-names behavior.  Later, we may should support putting check-names to ignore, but for now let them know it won't work and skip it
 | 
						|
                unless ($canonical =~ /^[a-z0-9-]+$/i) {
 | 
						|
                    xCAT::MsgUtils->message("E", {errorcode=>[1],error=>["$canonical contains invalid characters, skipping entry"]}, $callback, 1);
 | 
						|
                    next LINE;
 | 
						|
                }
 | 
						|
                if ($Cnames{$canonical} != 1)
 | 
						|
                {
 | 
						|
                    printf DOMAIN "%-20s IN  CNAME %s.%s.\n", $canonical,
 | 
						|
                      $canonical, $cpatrel{$netpat};
 | 
						|
                    $Cnames{$canonical} = 1;
 | 
						|
                }
 | 
						|
                next LINE;
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        # Check that the address is in the address list.
 | 
						|
        my $match = 'none';
 | 
						|
        foreach $netpat (@Netpatterns)
 | 
						|
        {
 | 
						|
            $match = $netpat, last
 | 
						|
              if ($addr =~ /^$netpat\./ or $addr =~ /^$netpat$/);
 | 
						|
        }
 | 
						|
        next if ($match eq 'none');
 | 
						|
 | 
						|
        ($canonical, $aliases) = split(' ', $names, 2);   # separate out aliases
 | 
						|
        next if ($dontdodomains && $canonical =~ /\./);   # skip domain names
 | 
						|
        $canonical =~ s/$Domainpattern//;    # strip off domain if there is one
 | 
						|
        unless ($canonical =~ /^[a-z0-9-]+$/i) {
 | 
						|
            xCAT::MsgUtils->message("E", {errorcode=>[1],error=>["$canonical contains invalid characters, skipping entry"]}, $callback, 1);
 | 
						|
            next;
 | 
						|
         }
 | 
						|
        $Hosts{$canonical} .= $addr . " ";   # index addresses by canonical name
 | 
						|
        $Aliases{$addr} .= $aliases . " ";   # index aliases by address
 | 
						|
        $Comments{"$canonical-$addr"} = $comment;
 | 
						|
 | 
						|
        # Print PTR records
 | 
						|
        my $file = $Netfiles{$match};
 | 
						|
        printf $file "%-30s\tIN  PTR   %s.%s.\n", &REVERSE($addr), $canonical,
 | 
						|
          $Domain;
 | 
						|
    }
 | 
						|
 | 
						|
    #
 | 
						|
    # Go through the list of canonical names.
 | 
						|
    # If there is more than 1 address associated with the
 | 
						|
    # name, it is a multi-homed host.  For each address
 | 
						|
    # look up the aliases since the aliases are associated
 | 
						|
    # with the address, not the canonical name.
 | 
						|
    #
 | 
						|
    foreach $canonical (keys %Hosts)
 | 
						|
    {
 | 
						|
        my @addrs = split(' ', $Hosts{$canonical});
 | 
						|
        my $numaddrs = $#addrs + 1;
 | 
						|
        foreach my $addr (@addrs)
 | 
						|
        {
 | 
						|
 | 
						|
            #
 | 
						|
            # Print address record for canonical name.
 | 
						|
            #
 | 
						|
            if ($Cnames{$canonical} != 1)
 | 
						|
            {
 | 
						|
                printf DOMAIN "%-20s IN  A     %s\n", $canonical, $addr;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "$canonical - cannot create A record because CNAME exists for name.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            }
 | 
						|
 | 
						|
            #
 | 
						|
            # Print cname or address records for each alias.
 | 
						|
            # If this is a multi-homed host, print an address
 | 
						|
            # record for each alias.  If this is a single address
 | 
						|
            # host, print a cname record.
 | 
						|
            #
 | 
						|
            my $alias;
 | 
						|
            if ($doaliases)
 | 
						|
            {
 | 
						|
                my @aliases = split(' ', $Aliases{$addr});
 | 
						|
                foreach $alias (@aliases)
 | 
						|
                {
 | 
						|
 | 
						|
                    #
 | 
						|
                    # Skip over the alias if the alias and canonical
 | 
						|
                    # name only differ in that one of them has the
 | 
						|
                    # domain appended to it.
 | 
						|
                    #
 | 
						|
                    next
 | 
						|
                      if ($dontdodomains && $alias =~ /\./); # skip domain names
 | 
						|
                    $alias =~ s/$Domainpattern//;
 | 
						|
                    if ($alias eq $canonical)
 | 
						|
                    {
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
                    unless ($alias  =~ /^[a-z0-9-]+$/i) {
 | 
						|
                        xCAT::MsgUtils->message("E", {errorcode=>[1],error=>["$canonical alias $alias contains invalid characters, skipping entry"]}, $callback, 1);
 | 
						|
                        next;
 | 
						|
                    }
 | 
						|
 | 
						|
                    my $aliasforallnames = 0;
 | 
						|
                    if ($numaddrs > 1)
 | 
						|
                    {
 | 
						|
 | 
						|
                        #
 | 
						|
                        # If alias exists for *all* addresses of this host, we
 | 
						|
                        # can use a CNAME instead of an address record.
 | 
						|
                        #
 | 
						|
                        my $aliasforallnames = 1;
 | 
						|
                        my $xalias = $alias . " "; # every alias ends with blank
 | 
						|
                        my @xaddrs = split(' ', $Hosts{$canonical});
 | 
						|
                        foreach my $xaddr (@xaddrs)
 | 
						|
                        {
 | 
						|
                            if (!($Aliases{$xaddr} =~ /\b$xalias/))
 | 
						|
                            {
 | 
						|
                                $aliasforallnames = 0;
 | 
						|
                            }
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if (($numaddrs > 1) && !$aliasforallnames)
 | 
						|
                    {
 | 
						|
                        printf DOMAIN "%-20s IN  A     %s\n", $alias, $addr;
 | 
						|
                    }
 | 
						|
                    else
 | 
						|
                    {
 | 
						|
 | 
						|
                        #
 | 
						|
                        # Flag aliases that have already been used
 | 
						|
                        # in CNAME records or have A records.
 | 
						|
                        #
 | 
						|
                        if (($Cnames{$alias} != 1) && (!$Hosts{$alias}))
 | 
						|
                        {
 | 
						|
                            printf DOMAIN "%-20s IN  CNAME %s.%s.\n", $alias,
 | 
						|
                              $canonical, $Domain;
 | 
						|
                            $Cnames{$alias} = 1;
 | 
						|
                        }
 | 
						|
                        else
 | 
						|
                        {
 | 
						|
                            my $rsp = {};
 | 
						|
                            $rsp->{data}->[0] =
 | 
						|
                              "$alias - CNAME or A exists already. alias ignored.\n";
 | 
						|
                            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
 | 
						|
                    if ($aliasforallnames)
 | 
						|
                    {
 | 
						|
 | 
						|
                        #
 | 
						|
                        # Since a CNAME record was created, remove this
 | 
						|
                        # name from the alias list so we don't encounter
 | 
						|
                        # it again for the next address of this host.
 | 
						|
                        #
 | 
						|
                        my $xalias = $alias . " "; # every alias ends with blank
 | 
						|
                        my @xaddrs = split(' ', $Hosts{$canonical});
 | 
						|
                        my $xaddr;
 | 
						|
                        foreach $xaddr (@xaddrs)
 | 
						|
                        {
 | 
						|
                            $Aliases{$xaddr} =~ s/\b$xalias//;
 | 
						|
                        }
 | 
						|
                    }
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($domx)
 | 
						|
        {
 | 
						|
            &MX($callback, $canonical, @addrs);
 | 
						|
        }
 | 
						|
        if ($dotxt)
 | 
						|
        {
 | 
						|
            &TXT($canonical, @addrs);
 | 
						|
        }
 | 
						|
        if ($Commentfile ne "")
 | 
						|
        {
 | 
						|
            &DO_COMMENTS($callback, $canonical, @addrs);
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Deal with spcl's
 | 
						|
    if (-r "spcl.$Domainfile")
 | 
						|
    {
 | 
						|
        print DOMAIN "\$INCLUDE spcl.$Domainfile\n";
 | 
						|
    }
 | 
						|
    my $file;
 | 
						|
    my $n;
 | 
						|
    foreach $n (@Networks)
 | 
						|
    {
 | 
						|
        if (-r "spcl.$n")
 | 
						|
        {
 | 
						|
            $file = "DB.$n";
 | 
						|
            print $file "\$INCLUDE spcl.$n\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # generate boot.* files
 | 
						|
    &GEN_BOOT($callback);
 | 
						|
    my $rsp = {};
 | 
						|
    $rsp->{data}->[0] = "Setup of DNS complete.";
 | 
						|
    xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
    exit 0;
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Generate resource record data for
 | 
						|
# strings from the commment field that
 | 
						|
# are found in the comment file (-C).
 | 
						|
#
 | 
						|
sub DO_COMMENTS
 | 
						|
{
 | 
						|
    my ($callback, $canonical, @addrs) = @_;
 | 
						|
    my (@c, $c, $a, $comments);
 | 
						|
 | 
						|
    if (!$Commentfileread)
 | 
						|
    {
 | 
						|
        unless (open(F, $Commentfile))
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Unable to open file $Commentfile: $!.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
        $Commentfileread++;
 | 
						|
        while (<F>)
 | 
						|
        {
 | 
						|
            chop;
 | 
						|
            my ($key, $c) = split(':', $_, 2);
 | 
						|
            $CommentRRs{$key} = $c;
 | 
						|
        }
 | 
						|
        close(F);
 | 
						|
    }
 | 
						|
 | 
						|
    my $key;
 | 
						|
    foreach $a (@addrs)
 | 
						|
    {
 | 
						|
        $key = "$canonical-$a";
 | 
						|
        $comments .= " $Comments{$key}";
 | 
						|
    }
 | 
						|
 | 
						|
    @c = split(' ', $comments);
 | 
						|
    foreach $c (@c)
 | 
						|
    {
 | 
						|
        if ($CommentRRs{$c})
 | 
						|
        {
 | 
						|
            printf DOMAIN "%-20s %s\n", $canonical, $CommentRRs{$c};
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Generate MX record data
 | 
						|
#
 | 
						|
sub MX
 | 
						|
{
 | 
						|
    my ($callback, $canonical, @addrs) = @_;
 | 
						|
    my ($first, $a, $key, $comments);
 | 
						|
 | 
						|
    if ($Cnames{$canonical})
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] =
 | 
						|
          "$canonical - cannot create MX record because CNAME exists for name.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        return;
 | 
						|
    }
 | 
						|
    $first = 1;
 | 
						|
 | 
						|
    foreach $a (@addrs)
 | 
						|
    {
 | 
						|
        $key = "$canonical-$a";
 | 
						|
        $comments .= " $Comments{$key}";
 | 
						|
    }
 | 
						|
 | 
						|
    if ($comments !~ /\[no smtp\]/)
 | 
						|
    {
 | 
						|
 | 
						|
        # Add WKS if requested
 | 
						|
        if ($dowks)
 | 
						|
        {
 | 
						|
            foreach $a (@addrs)
 | 
						|
            {
 | 
						|
                printf DOMAIN "%-20s IN  WKS   %s TCP SMTP\n", $canonical, $a;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        printf DOMAIN "%-20s IN  MX    %s %s.%s.\n", $canonical, $DefMxWeight,
 | 
						|
          $canonical, $Domain;
 | 
						|
        $first = 0;
 | 
						|
    }
 | 
						|
    if ($#Mx >= 0)
 | 
						|
    {
 | 
						|
        foreach $a (@Mx)
 | 
						|
        {
 | 
						|
            if ($first)
 | 
						|
            {
 | 
						|
                printf DOMAIN "%-20s IN  MX    %s\n", $canonical, $a;
 | 
						|
                $first = 0;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                printf DOMAIN "%-20s IN  MX    %s\n", "", $a;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Generate TXT record data
 | 
						|
#
 | 
						|
sub TXT
 | 
						|
{
 | 
						|
    my ($canonical, @addrs) = @_;
 | 
						|
    my ($a, $key, $comments);
 | 
						|
 | 
						|
    foreach $a (@addrs)
 | 
						|
    {
 | 
						|
        $key = "$canonical-$a";
 | 
						|
        $comments .= " $Comments{$key}";
 | 
						|
    }
 | 
						|
    $comments =~ s/\[no smtp\]//g;
 | 
						|
    $comments =~ s/^\s*//;
 | 
						|
    $comments =~ s/\s*$//;
 | 
						|
 | 
						|
    if ($comments ne "")
 | 
						|
    {
 | 
						|
        printf DOMAIN "%s IN  TXT   \"%s\"\n", $canonical, $comments;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Create the SOA record at the beginning of the file
 | 
						|
#
 | 
						|
sub MAKE_SOA
 | 
						|
{
 | 
						|
    my ($callback, $fname, $file) = @_;
 | 
						|
    my ($s);
 | 
						|
 | 
						|
    if (-s $fname)
 | 
						|
    {
 | 
						|
 | 
						|
        unless (open($file, "$fname"))
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Unable to open $fname: $!.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
        $_ = <$file>;
 | 
						|
        chop;
 | 
						|
        if (/\($/)
 | 
						|
        {
 | 
						|
            my $junk;
 | 
						|
            if (!$soa_warned)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Converting SOA format to new style.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                $soa_warned++;
 | 
						|
            }
 | 
						|
            if ($ForceSerial > 0)
 | 
						|
            {
 | 
						|
                $Serial = $ForceSerial;
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                ($Serial, $junk) = split(' ', <$file>, 2);
 | 
						|
                $Serial++;
 | 
						|
                if ($UseDateInSerial && ($DateSerial > $Serial))
 | 
						|
                {
 | 
						|
                    $Serial = $DateSerial;
 | 
						|
                }
 | 
						|
            }
 | 
						|
            ($Refresh, $junk) = split(' ', <$file>, 2);
 | 
						|
            ($Retry,   $junk) = split(' ', <$file>, 2);
 | 
						|
            ($Expire,  $junk) = split(' ', <$file>, 2);
 | 
						|
            ($Ttl,     $junk) = split(' ', <$file>, 2);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if (/TTL/)
 | 
						|
            {
 | 
						|
                $_ = <$file>;
 | 
						|
            }
 | 
						|
            split(' ');
 | 
						|
            if ($#_ == 11)
 | 
						|
            {
 | 
						|
                if ($ForceSerial > 0)
 | 
						|
                {
 | 
						|
                    $Serial = $ForceSerial;
 | 
						|
                }
 | 
						|
                else
 | 
						|
                {
 | 
						|
                    $Serial = ++$_[6];
 | 
						|
                    if ($UseDateInSerial && ($DateSerial > $Serial))
 | 
						|
                    {
 | 
						|
                        $Serial = $DateSerial;
 | 
						|
                    }
 | 
						|
                }
 | 
						|
                $Refresh = $_[7];
 | 
						|
                $Retry   = $_[8];
 | 
						|
                $Expire  = $_[9];
 | 
						|
                $Ttl     = $_[10];
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Improper format SOA in $fname.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        if ($UseDefSOAValues)
 | 
						|
        {
 | 
						|
            $Refresh = $DefRefresh;
 | 
						|
            $Retry   = $DefRetry;
 | 
						|
            $Expire  = $DefExpire;
 | 
						|
            $Ttl     = $DefTtl;
 | 
						|
        }
 | 
						|
        close($file);
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if ($ForceSerial > 0)
 | 
						|
        {
 | 
						|
            $Serial = $ForceSerial;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            $Serial = $DefSerial;
 | 
						|
            if ($UseDateInSerial && ($DateSerial > $Serial))
 | 
						|
            {
 | 
						|
                $Serial = $DateSerial;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $Refresh = $DefRefresh;
 | 
						|
        $Retry   = $DefRetry;
 | 
						|
        $Expire  = $DefExpire;
 | 
						|
        $Ttl     = $DefTtl;
 | 
						|
        close($file);
 | 
						|
    }
 | 
						|
 | 
						|
    unless (open($file, "> $fname"))
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "Unable to open $fname: $!.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        exit 1;
 | 
						|
    }
 | 
						|
    print $file '$TTL 86400' . "\n";
 | 
						|
    print $file "\@ IN  SOA $RespHost $RespUser ";
 | 
						|
    print $file "( $Serial $Refresh $Retry $Expire $Ttl )\n";
 | 
						|
    foreach $s (@Servers)
 | 
						|
    {
 | 
						|
        print $file "  IN  NS  $s\n";
 | 
						|
    }
 | 
						|
    print $file "\n";
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Reverse the octets of an IP address and append
 | 
						|
# in-addr.arpa.
 | 
						|
#
 | 
						|
sub REVERSE
 | 
						|
{
 | 
						|
    join('.', reverse(split('\.', $_[0]))) . '.IN-ADDR.ARPA.';
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Establish what we will be using for SOA records
 | 
						|
#
 | 
						|
sub FIXUP
 | 
						|
{
 | 
						|
    my $callback = shift;
 | 
						|
    my ($s);
 | 
						|
 | 
						|
    if ($Host =~ /\./)
 | 
						|
    {
 | 
						|
        $RespHost = "$Host.";
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        $RespHost = "$Host.$Domain.";
 | 
						|
    }
 | 
						|
    $RespHost =~ s/\.\././g;
 | 
						|
 | 
						|
    if ($User =~ /@/)
 | 
						|
    {    # -u user@...
 | 
						|
        if ($User =~ /\./)
 | 
						|
        {
 | 
						|
            $RespUser = "$User.";    # -u user@terminator.movie.edu
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            $RespUser = "$User.$Domain.";    # -u user@terminator
 | 
						|
        }
 | 
						|
        $RespUser =~ s/@/./;
 | 
						|
    }
 | 
						|
    elsif ($User =~ /\./)
 | 
						|
    {
 | 
						|
        $RespUser = "$User.";                # -u user.terminator.movie.edu
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        $RespUser = "$User.$RespHost";       # -u user
 | 
						|
    }
 | 
						|
    $RespUser =~ s/\.\././g;                 # Strip any ".."'s to "."
 | 
						|
 | 
						|
    # Clean up nameservers
 | 
						|
    if (!@Servers)
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] =
 | 
						|
          "No -s option specified.  Assuming \"-s $Host.$Domain\".\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        push(@Servers, "$Host.$Domain.");
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        foreach $s (@Servers)
 | 
						|
        {
 | 
						|
            if ($s !~ /\./)
 | 
						|
            {
 | 
						|
                $s .= ".$Domain";
 | 
						|
            }
 | 
						|
            if ($s !~ /\.$/)
 | 
						|
            {
 | 
						|
                $s .= ".";
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Clean up MX hosts
 | 
						|
    foreach $s (@Mx)
 | 
						|
    {
 | 
						|
        $s =~ s/:/ /;
 | 
						|
        if ($s !~ /\./)
 | 
						|
        {
 | 
						|
            $s .= ".$Domain";
 | 
						|
        }
 | 
						|
        if ($s !~ /\.$/)
 | 
						|
        {
 | 
						|
            $s .= ".";
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Now open boot file (named.conf)  and print saved data
 | 
						|
    unless (open(BOOT, "> $Bootfile"))
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "Unable to  open $Bootfile.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        exit 1;
 | 
						|
    }
 | 
						|
 | 
						|
    #
 | 
						|
    # Write either the version 4 boot file directives or the
 | 
						|
    # version 8 boot file directives.
 | 
						|
    #
 | 
						|
 | 
						|
    if ($Version == 4)
 | 
						|
    {
 | 
						|
        print BOOT "\ndirectory $DBDir\n";
 | 
						|
        foreach my $line (@bootmsgs_v4)
 | 
						|
        {
 | 
						|
            print BOOT $line;
 | 
						|
        }
 | 
						|
        print BOOT "cache\t. db.cache\n";
 | 
						|
        if (-r "spcl.boot")
 | 
						|
        {
 | 
						|
            print BOOT "include\tspcl.boot\n";
 | 
						|
        }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        print BOOT qq|\noptions {\n\tdirectory "$DBDir";\n|;
 | 
						|
        if (@forwarders)
 | 
						|
        {
 | 
						|
            print BOOT qq|\tforwarders {\n|;
 | 
						|
            foreach (@forwarders)
 | 
						|
            {
 | 
						|
                print BOOT qq|\t\t$_;\n|;
 | 
						|
            }
 | 
						|
            print BOOT qq|\t};\n|;
 | 
						|
        }
 | 
						|
        if (-r "spcl.options")
 | 
						|
        {
 | 
						|
            print BOOT "\t# These options came from the file spcl.options\n";
 | 
						|
 | 
						|
            #
 | 
						|
            # Copy the options in since "include" cannot be used
 | 
						|
            # within a statement.
 | 
						|
            #
 | 
						|
            unless (open(OPTIONS, "<spcl.options"))
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Unable to open spcl.options.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit 1;
 | 
						|
            }
 | 
						|
            while (<OPTIONS>)
 | 
						|
            {
 | 
						|
                print BOOT;
 | 
						|
            }
 | 
						|
            close(OPTIONS);
 | 
						|
        }
 | 
						|
        print BOOT qq|};\n\n|;
 | 
						|
        foreach my $line (@bootmsgs_v8)
 | 
						|
        {
 | 
						|
            print BOOT $line;
 | 
						|
        }
 | 
						|
        unless (@forwarders)
 | 
						|
        {
 | 
						|
            print BOOT
 | 
						|
              qq|zone "." in {\n\ttype hint;\n\tfile "db.cache";\n};\n\n|;
 | 
						|
        }
 | 
						|
        if (-r "spcl.boot")
 | 
						|
        {
 | 
						|
            print BOOT qq|include "spcl.boot";\n\n|;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    # Go ahead and start creating files and making SOA's
 | 
						|
    my $x1;
 | 
						|
    my $x2;
 | 
						|
    foreach my $i (@makesoa)
 | 
						|
    {
 | 
						|
        ($x1, $x2) = split(' ', $i);
 | 
						|
        &MAKE_SOA($callback, $x1, $x2);
 | 
						|
    }
 | 
						|
    printf DOMAIN "%-20s IN  A     127.0.0.1\n", "localhost";
 | 
						|
 | 
						|
    my $file = "DB.127.0.0.1";
 | 
						|
    &MAKE_SOA($callback, $DBDir . "db.127.0.0", $file);
 | 
						|
    my $nothing;
 | 
						|
    open($nothing, ">>", $DBDir . "db.cache");
 | 
						|
    close($nothing);
 | 
						|
    printf $file "%-30s\tIN  PTR   localhost.\n", &REVERSE("127.0.0.1");
 | 
						|
    close($file);
 | 
						|
}
 | 
						|
 | 
						|
sub PARSEARGS
 | 
						|
{
 | 
						|
    my ($callback, @args) = @_;
 | 
						|
    my ($i, $net, $subnetmask, $option, $tmp1);
 | 
						|
    my ($file, @newargs, @targs);
 | 
						|
    my ($sec, $min, $hour, $mday, $mon, $year, $rest);
 | 
						|
    ($sec, $min, $hour, $mday, $mon, $year, $rest) = localtime(time);
 | 
						|
    $DateSerial =
 | 
						|
      ($mday * 100) + (($mon + 1) * 10000) + (($year + 1900) * 1000000);
 | 
						|
 | 
						|
    $i = 0;
 | 
						|
    while ($i <= $#args)
 | 
						|
    {
 | 
						|
        $option = $args[$i];
 | 
						|
        if ($option eq "-d")
 | 
						|
        {
 | 
						|
            if ($Domain ne "")
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Only one -d option allowed.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
            $Domain        = $args[++$i];
 | 
						|
            $Domainpattern = "." . $Domain;
 | 
						|
            $Domainpattern =~ s/\./\\./g;    # for stripping off domain
 | 
						|
 | 
						|
            # Add entry to the boot file.
 | 
						|
            $Domainfile = $Domain;
 | 
						|
            $Domainfile =~ s/\..*//;
 | 
						|
            push(@makesoa,     $DBDir . "db.$Domainfile DOMAIN");
 | 
						|
            push(@bootmsgs_v4, "primary\t$Domain db.$Domainfile\n");
 | 
						|
            push(@bootmsgs_v8,
 | 
						|
                 qq|zone "$Domain" in {\n\ttype master;\n\tfile "db.$Domainfile";\n};\n\n|
 | 
						|
                 );
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-f")
 | 
						|
        {
 | 
						|
            $file = $args[++$i];
 | 
						|
            unless (open(F, $file))
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Unable to open args file $file: $!.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit 1;
 | 
						|
            }
 | 
						|
            while (<F>)
 | 
						|
            {
 | 
						|
                next if (/^#/);
 | 
						|
                next if (/^$/);
 | 
						|
                chop;
 | 
						|
                @targs = split(' ');
 | 
						|
                push(@newargs, @targs);
 | 
						|
            }
 | 
						|
            close(F);
 | 
						|
            &PARSEARGS($callback, @newargs);
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-z")
 | 
						|
        {
 | 
						|
            $Bootsecsaveaddr = $args[++$i];
 | 
						|
            if (!defined($Bootsecaddr))
 | 
						|
            {
 | 
						|
                $Bootsecaddr = $Bootsecsaveaddr;
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-Z")
 | 
						|
        {
 | 
						|
            $Bootsecaddr = $args[++$i];
 | 
						|
            if (!defined($Bootsecsaveaddr))
 | 
						|
            {
 | 
						|
                $Bootsecsaveaddr = $Bootsecaddr;
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-b")
 | 
						|
        {
 | 
						|
            $Bootfile = $args[++$i];
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-A")
 | 
						|
        {
 | 
						|
            $doaliases = 0;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-M")
 | 
						|
        {
 | 
						|
            $domx = 0;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-w")
 | 
						|
        {
 | 
						|
            $dowks = 1;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-D")
 | 
						|
        {
 | 
						|
            $dontdodomains = 1;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-t")
 | 
						|
        {
 | 
						|
            $dotxt = 1;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-u")
 | 
						|
        {
 | 
						|
            $User = $args[++$i];
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-s")
 | 
						|
        {
 | 
						|
            while ($args[++$i] !~ /^-/ && $i <= $#args)
 | 
						|
            {
 | 
						|
                push(@Servers, $args[$i]);
 | 
						|
            }
 | 
						|
            $i--;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-m")
 | 
						|
        {
 | 
						|
            if ($args[++$i] !~ /:/)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "Improper format for -m option ignored ($args[$i]).\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            }
 | 
						|
            push(@Mx, $args[$i]);
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-c")
 | 
						|
        {
 | 
						|
            my $tmp1 = $args[++$i];
 | 
						|
            if ($tmp1 !~ /\./)
 | 
						|
            {
 | 
						|
                $tmp1 .= ".$Domain";
 | 
						|
            }
 | 
						|
            if ($Domain eq $tmp1)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "Domain for -c option must not match domain for -d option.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
            my $tmp2 = $tmp1;
 | 
						|
            $tmp2 =~ s/\./\\./g;
 | 
						|
            $cpatrel{$tmp2} = $tmp1;
 | 
						|
            push(@cpats, $tmp2);
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-e")
 | 
						|
        {
 | 
						|
            $tmp1 = $args[++$i];
 | 
						|
            if ($tmp1 !~ /\./)
 | 
						|
            {
 | 
						|
                $tmp1 .= ".$Domain";
 | 
						|
            }
 | 
						|
            $tmp1 =~ s/\./\\./g;
 | 
						|
            push(@elimpats, $tmp1);
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-h")
 | 
						|
        {
 | 
						|
            $Host = $args[++$i];
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-o")
 | 
						|
        {
 | 
						|
            if ($args[++$i] !~ /^[:\d]*$/
 | 
						|
                || split(':', $args[$i]) != 4)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Improper format for -o ($args[$i]).\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
            ($DefRefresh, $DefRetry, $DefExpire, $DefTtl) =
 | 
						|
              split(':', $args[$i]);
 | 
						|
            $UseDefSOAValues = 1;
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-i")
 | 
						|
        {
 | 
						|
            $ForceSerial = $args[++$i];
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-H")
 | 
						|
        {
 | 
						|
            $Hostfile = $args[++$i];
 | 
						|
            if (!-r $Hostfile || -z $Hostfile)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "Invalid file specified for -H ($Hostfile).\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-C")
 | 
						|
        {
 | 
						|
            $Commentfile = $args[++$i];
 | 
						|
            if (!-r $Commentfile || -z $Commentfile)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "Invalid file specified for -C ($Commentfile).\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-N")
 | 
						|
        {
 | 
						|
            $Defsubnetmask = $args[++$i];
 | 
						|
            if ($Defsubnetmask !~ /^[.\d]*$/
 | 
						|
                || split('\.', $Defsubnetmask) != 4)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Improper subnet mask ($Defsubnetmask).\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                exit(1);
 | 
						|
            }
 | 
						|
            if ($#Networks >= 0)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "-N option should be specified before any -n options.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        elsif ($option eq "-n")
 | 
						|
        {
 | 
						|
            (my $tnet, $subnetmask) = split(':', $args[++$i]);
 | 
						|
            $net = "";
 | 
						|
            my @netm  = split(/\./, $subnetmask);
 | 
						|
            my @tnets = split(/\./, $tnet);
 | 
						|
            foreach (0 .. 3)
 | 
						|
            {
 | 
						|
                my $res = ($tnets[$_] + 0) & ($netm[$_] + 0);
 | 
						|
                if ($netm[$_])
 | 
						|
                {
 | 
						|
                    $net .= $res . '.';
 | 
						|
                }
 | 
						|
            }
 | 
						|
            $net =~ s/\.$//;
 | 
						|
 | 
						|
            if (not $net)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "Empty network found in networks table (i.e. ,,),This is almost certainly going to cause a problem....\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            }
 | 
						|
            if ($subnetmask eq "")
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] =
 | 
						|
                  "$net has no defined netmask in the networks table, the result will probably be wrong.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                foreach $tmp1 (&SUBNETS($net, $Defsubnetmask))
 | 
						|
                {
 | 
						|
                    &BUILDNET($tmp1);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            else
 | 
						|
            {
 | 
						|
                if ($subnetmask !~ /^[.\d]*$/
 | 
						|
                    || split('\.', $subnetmask) != 4)
 | 
						|
                {
 | 
						|
                    my $rsp = {};
 | 
						|
                    $rsp->{data}->[0] = "Improper subnet mask ($subnetmask).\n";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                    exit(1);
 | 
						|
                }
 | 
						|
                foreach $tmp1 (&SUBNETS($net, $subnetmask))
 | 
						|
                {
 | 
						|
                    &BUILDNET($tmp1);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            if ($option =~ /^-.*/)
 | 
						|
            {
 | 
						|
                my $rsp = {};
 | 
						|
                $rsp->{data}->[0] = "Unknown option: $option ... ignored.\n";
 | 
						|
                xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $i++;
 | 
						|
    }
 | 
						|
 | 
						|
    if (!@Networks || $Domain eq "")
 | 
						|
    {
 | 
						|
        my $rsp = {};
 | 
						|
        $rsp->{data}->[0] = "Must specify one -d and at least one -n.\n";
 | 
						|
        xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
        exit(1);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
sub BUILDNET
 | 
						|
{
 | 
						|
    my ($net) = @_;
 | 
						|
 | 
						|
    push(@Networks, $net);
 | 
						|
 | 
						|
    #
 | 
						|
    # Create pattern to match against.
 | 
						|
    # The dots must be changed to \. so they
 | 
						|
    # aren't used as wildcards.
 | 
						|
    #
 | 
						|
    my $netpat = $net;
 | 
						|
    $netpat =~ s/\./\\./g;
 | 
						|
    push(@Netpatterns, $netpat);
 | 
						|
 | 
						|
    #
 | 
						|
    # Create db files for PTR records.
 | 
						|
    # Save the file names in an array for future use.
 | 
						|
    #
 | 
						|
    my $netfile = "DB.$net";
 | 
						|
    $Netfiles{$netpat} = $netfile;
 | 
						|
    push(@makesoa, $DBDir . "db.$net $netfile");
 | 
						|
 | 
						|
    # Add entry to the boot file.
 | 
						|
    my $revaddr = &REVERSE($net);
 | 
						|
    chop($revaddr);    # remove trailing dot
 | 
						|
    push(@bootmsgs_v4, "primary $revaddr db.$net\n");
 | 
						|
    push(@bootmsgs_v8,
 | 
						|
         qq|zone "$revaddr" in {\n\ttype master;\n\tfile "db.$net";\n};\n\n|);
 | 
						|
}
 | 
						|
 | 
						|
#
 | 
						|
# Calculate all the subnets from a network number and mask.
 | 
						|
# This was originally written for awk, not perl.
 | 
						|
#
 | 
						|
sub SUBNETS
 | 
						|
{
 | 
						|
    my ($network, $mask) = @_;
 | 
						|
    my (@ans, @net, @mask, $buf, $number, $i, $j, $howmany);
 | 
						|
 | 
						|
    @net  = split(/\./, $network);
 | 
						|
    @mask = split(/\./, $mask);
 | 
						|
    $number = '';
 | 
						|
 | 
						|
    #
 | 
						|
    # Only expand bytes 1, 2, or 3
 | 
						|
    # for DNS purposes
 | 
						|
    #
 | 
						|
    for ($i = 0 ; $i < 4 ; $i++)
 | 
						|
    {
 | 
						|
        if ($mask[$i] == 255)
 | 
						|
        {
 | 
						|
            $number = $number . $net[$i] . '.';
 | 
						|
        }
 | 
						|
        elsif (($mask[$i] == 0) || $mask[$i] eq '')
 | 
						|
        {
 | 
						|
            push(@ans, $network);
 | 
						|
            last;
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
 | 
						|
            #
 | 
						|
            # This should be done as a bit-wise or
 | 
						|
            # but awk does not have an or symbol
 | 
						|
            #
 | 
						|
            $howmany = 255 - $mask[$i];
 | 
						|
            for ($j = 0 ; $j <= $howmany ; $j++)
 | 
						|
            {
 | 
						|
                if ($net[$i] + $j <= 255)
 | 
						|
                {
 | 
						|
                    $buf = sprintf("%s%d", $number, $net[$i] + $j);
 | 
						|
                    push(@ans, $buf);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            last;
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    if ($#ans == -1)
 | 
						|
    {
 | 
						|
        push(@ans, $network);
 | 
						|
    }
 | 
						|
 | 
						|
    @ans;
 | 
						|
}
 | 
						|
 | 
						|
sub GEN_BOOT
 | 
						|
{
 | 
						|
    $callback = shift;
 | 
						|
    my ($revaddr, $n);
 | 
						|
 | 
						|
    if (0)
 | 
						|
    {    #! -e "boot.cacheonly") { DISABLE THIS PART
 | 
						|
            #
 | 
						|
            # Create a boot file for a cache-only server
 | 
						|
            #
 | 
						|
        unless (open(F, ">boot.cacheonly"))
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Unable to open boot.cacheonly: $!.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
        if ($Version == 4)
 | 
						|
        {
 | 
						|
            print F "directory\t$DBDir\n";
 | 
						|
            print F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
 | 
						|
            print F "cache\t\t.                       db.cache\n";
 | 
						|
            if (-r "spcl.cacheonly")
 | 
						|
            {
 | 
						|
                printf F "include\t\tspcl.cacheonly\n";
 | 
						|
            }
 | 
						|
            close(F);
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            print F qq|\noptions {\n\tdirectory "$DBDir";\n|;
 | 
						|
            if (@forwarders)
 | 
						|
            {
 | 
						|
                print F qq|\tforwarders {\n|;
 | 
						|
                foreach (@forwarders)
 | 
						|
                {
 | 
						|
                    print F qq|\t\t$_;\n|;
 | 
						|
                }
 | 
						|
                print F qq|\t};\n|;
 | 
						|
            }
 | 
						|
            if (-r "spcl.options")
 | 
						|
            {
 | 
						|
                print F "\t# These options came from the file spcl.options\n";
 | 
						|
 | 
						|
                #
 | 
						|
                # Copy the options in since "include" cannot be used
 | 
						|
                # within a statement.
 | 
						|
                #
 | 
						|
 | 
						|
                unless (open(OPTIONS, "<spcl.options"))
 | 
						|
                {
 | 
						|
                    my $rsp = {};
 | 
						|
                    $rsp->{data}->[0] = "Unable to open boot.cacheonly: $!.\n";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                    exit 1;
 | 
						|
                }
 | 
						|
 | 
						|
                while (<OPTIONS>)
 | 
						|
                {
 | 
						|
                    print F;
 | 
						|
                }
 | 
						|
                close(OPTIONS);
 | 
						|
            }
 | 
						|
            print F qq|};\n\n|;
 | 
						|
            print F qq|zone "0.0.127.IN-ADDR.ARPA" in {\n\ttype master;|;
 | 
						|
            print F qq|\n\tfile "db.127.0.0";|;
 | 
						|
            print F qq|\n\tnotify no;\n};\n\n|;
 | 
						|
 | 
						|
            #print F qq|zone "." in {\n\ttype hint;\n\tfile "db.cache";\n};\n\n|;
 | 
						|
            if (-r "spcl.cacheonly")
 | 
						|
            {
 | 
						|
                print F qq|include "spcl.cacheonly";\n\n|;
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
 | 
						|
    #
 | 
						|
    # Create a 2 boot files for a secondary (slave) servers.
 | 
						|
    # One boot file doesn't save the zone data in a file.  The
 | 
						|
    # other boot file does save the zone data in a file.
 | 
						|
    #
 | 
						|
    if (defined($Bootsecaddr))
 | 
						|
    {
 | 
						|
        unless (open(F, ">boot.sec"))
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Unable to open boot.sec: $!.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
 | 
						|
        if ($Version == 4)
 | 
						|
        {
 | 
						|
            print F "directory\t$DBDir\n";
 | 
						|
            print F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
 | 
						|
            printf F "secondary\t%-23s $Bootsecaddr\n", $Domain;
 | 
						|
            foreach $n (@Networks)
 | 
						|
            {
 | 
						|
                $revaddr = &REVERSE($n);
 | 
						|
                chop($revaddr);
 | 
						|
                printf F "secondary\t%-23s $Bootsecaddr\n", $revaddr;
 | 
						|
            }
 | 
						|
            print F "cache\t\t.                       db.cache\n";
 | 
						|
            if (-r "spcl.boot")
 | 
						|
            {
 | 
						|
                printf F "include\t\tspcl.boot\n";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            print F qq|\noptions {\n\tdirectory "$DBDir";\n|;
 | 
						|
            if (-r "spcl.options")
 | 
						|
            {
 | 
						|
                print F "\t# These options came from the file spcl.options\n";
 | 
						|
 | 
						|
                #
 | 
						|
                # Copy the options in since "include" cannot be used
 | 
						|
                # within a statement.
 | 
						|
                #
 | 
						|
                unless (open(OPTIONS, "<spcl.options"))
 | 
						|
                {
 | 
						|
                    my $rsp = {};
 | 
						|
                    $rsp->{data}->[0] = "Unable to open spcl.options.\n";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                    exit 1;
 | 
						|
                }
 | 
						|
 | 
						|
                while (<OPTIONS>)
 | 
						|
                {
 | 
						|
                    print F;
 | 
						|
                }
 | 
						|
                close(OPTIONS);
 | 
						|
            }
 | 
						|
            print F qq|};\n\n|;
 | 
						|
            print F qq|zone "0.0.127.IN-ADDR.ARPA" in {\n\ttype master;|;
 | 
						|
            print F qq|\n\tfile "db.127.0.0";|;
 | 
						|
            print F qq|\n\tnotify no;\n};\n\n|;
 | 
						|
            print F qq|zone "$Domain" in {\n\ttype slave;\n\tmasters {|;
 | 
						|
            print F qq| $Bootsecaddr; };\n};\n\n|;
 | 
						|
 | 
						|
            foreach $n (@Networks)
 | 
						|
            {
 | 
						|
                $revaddr = &REVERSE($n);
 | 
						|
                chop($revaddr);
 | 
						|
                print F qq|zone "$revaddr" in {\n\ttype slave;\n\tmasters {|;
 | 
						|
                print F qq| $Bootsecaddr; };\n};\n\n|;
 | 
						|
            }
 | 
						|
 | 
						|
            #print F qq|zone "." in {\n\ttype hint;\n\tfile "db.cache";\n};\n\n|;
 | 
						|
            if (-r "spcl.boot")
 | 
						|
            {
 | 
						|
                print F qq|include "spcl.boot";\n\n|;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        close(F);
 | 
						|
 | 
						|
        unless (open(F, ">boot.sec.save"))
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Unable to open  boot.sec.save: $!.\n";
 | 
						|
            xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
            exit 1;
 | 
						|
        }
 | 
						|
 | 
						|
        if ($Version == 4)
 | 
						|
        {
 | 
						|
            print F "directory\t$DBDir\n";
 | 
						|
            print F "primary\t\t0.0.127.IN-ADDR.ARPA    db.127.0.0\n";
 | 
						|
            printf F "secondary\t%-23s $Bootsecsaveaddr db.%s\n", $Domain,
 | 
						|
              $Domainfile;
 | 
						|
            foreach $n (@Networks)
 | 
						|
            {
 | 
						|
                $revaddr = &REVERSE($n);
 | 
						|
                chop($revaddr);
 | 
						|
                printf F "secondary\t%-23s $Bootsecsaveaddr db.%s\n", $revaddr,
 | 
						|
                  $n;
 | 
						|
            }
 | 
						|
            print F "cache\t\t.                       db.cache\n";
 | 
						|
            if (-r "spcl.boot")
 | 
						|
            {
 | 
						|
                printf F "include\t\tspcl.boot\n";
 | 
						|
            }
 | 
						|
        }
 | 
						|
        else
 | 
						|
        {
 | 
						|
            print F qq|\noptions {\n\tdirectory "$DBDir";\n|;
 | 
						|
            if (-r "spcl.options")
 | 
						|
            {
 | 
						|
                print F "\t# These options came from the file spcl.options\n";
 | 
						|
 | 
						|
                #
 | 
						|
                # Copy the options in since "include" cannot be used
 | 
						|
                # within a statement.
 | 
						|
                #
 | 
						|
                unless (open(OPTIONS, "<spcl.options"))
 | 
						|
                {
 | 
						|
                    my $rsp = {};
 | 
						|
                    $rsp->{data}->[0] = "Can't open spcl.options.\n";
 | 
						|
                    xCAT::MsgUtils->message("E", $rsp, $callback, 1);
 | 
						|
                    exit 1;
 | 
						|
                }
 | 
						|
                while (<OPTIONS>)
 | 
						|
                {
 | 
						|
                    print F;
 | 
						|
                }
 | 
						|
                close(OPTIONS);
 | 
						|
            }
 | 
						|
            print F qq|};\n\n|;
 | 
						|
            print F qq|zone "0.0.127.IN-ADDR.ARPA" in {\n\ttype master;|;
 | 
						|
            print F qq|\n\tfile "db.127.0.0";|;
 | 
						|
            print F qq|\n\tnotify no;\n};\n\n|;
 | 
						|
 | 
						|
            print F
 | 
						|
              qq|zone "$Domain" in {\n\ttype slave;\n\tfile "db.$Domainfile";|;
 | 
						|
            print F qq|\n\tmasters { $Bootsecsaveaddr; };\n};\n\n|;
 | 
						|
 | 
						|
            foreach $n (@Networks)
 | 
						|
            {
 | 
						|
                $revaddr = &REVERSE($n);
 | 
						|
                chop($revaddr);
 | 
						|
                print F
 | 
						|
                  qq|zone "$revaddr" in {\n\ttype slave;\n\tfile "db.$n";\n\tmasters {|;
 | 
						|
                print F qq| $Bootsecsaveaddr; };\n};\n\n|;
 | 
						|
            }
 | 
						|
 | 
						|
            #print F qq|zone "." in {\n\ttype hint;\n\tfile "db.cache";\n};\n\n|;
 | 
						|
            if (-r "spcl.boot")
 | 
						|
            {
 | 
						|
                print F qq|include "spcl.boot";\n\n|;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        close(F);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
# subroutine to display the usage
 | 
						|
sub checkusageandversion
 | 
						|
{
 | 
						|
    my $callback = shift;
 | 
						|
 | 
						|
    # parse the options
 | 
						|
    if (
 | 
						|
        GetOptions('h|help'    => \$::HELP,
 | 
						|
                   'v|version' => \$::VERSION)
 | 
						|
      )
 | 
						|
    {
 | 
						|
        if ($::HELP)
 | 
						|
        {
 | 
						|
            my $rsp = {};
 | 
						|
            $rsp->{data}->[0] = "Usage:";
 | 
						|
            $rsp->{data}->[1] = "  makedns <options>";
 | 
						|
            $rsp->{data}->[2] = "  makedns [-h|--help|-v|--version]";
 | 
						|
            $rsp->{data}->[3] = "     <options> See man makedns";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            exit 0;
 | 
						|
        }
 | 
						|
        if ($::VERSION)
 | 
						|
        {
 | 
						|
            my $version = xCAT::Utils->Version();
 | 
						|
            my $rsp     = {};
 | 
						|
            $rsp->{data}->[0] = "$version";
 | 
						|
            xCAT::MsgUtils->message("I", $rsp, $callback);
 | 
						|
            exit 0;
 | 
						|
        }
 | 
						|
    }
 | 
						|
    return;
 | 
						|
}
 | 
						|
 | 
						|
1;
 |