diff options
Diffstat (limited to 'bin/bind.import')
| -rwxr-xr-x | bin/bind.import | 235 | 
1 files changed, 235 insertions, 0 deletions
| diff --git a/bin/bind.import b/bin/bind.import new file mode 100755 index 000000000..45db2e210 --- /dev/null +++ b/bin/bind.import @@ -0,0 +1,235 @@ +#!/usr/bin/perl -w +# +# REQUIRED: +# -p: part number for domains +# +# -n: named.conf file (or an include file with zones you want to import), +#     for example root@ns.isp.com:/var/named/named.conf +# +# OPTIONAL: +# -d: dry-run, debug: don't insert any records, just dump debugging output +# -e: use existing domains records in Freeside +# -s: import slave zones as master.  useful if you need to recreate your +#     primary nameserver from a secondary +# -c dir: override patch for downloading zone files (for example, when +#         downloading zone files from chrooted bind) +# +# need to manually put header in +#  /usr/local/etc/freeside/export.<datasrc./bind/<machine>/named.conf.HEADER +# (or, nowadays, better just to include the file freeside exports) + +use strict; + +use vars qw($domain_svcpart); + +use Getopt::Std; +use Data::Dumper; +#use BIND::Conf_Parser; +#use DNS::ZoneParse 0.81; + +use Net::SCP qw(scp iscp); + +use FS::UID qw(adminsuidsetup datasrc); +use FS::Record qw(qsearch); #qsearchs); +#use FS::svc_acct_sm; +use FS::svc_domain; +use FS::domain_record; +#use FS::svc_acct; +#use FS::part_svc; + +use vars qw($opt_p $opt_n $opt_s $opt_c $opt_d $opt_e); +getopts("p:n:sc:de"); + +my $user = shift or die &usage; +adminsuidsetup $user; + +$FS::svc_Common::noexport_hack = 1; +$FS::domain_record::noserial_hack = 1; + +use vars qw($spooldir); +$spooldir = "/usr/local/etc/freeside/export.". datasrc. "/bind"; +mkdir $spooldir unless -d $spooldir; + +$domain_svcpart = $opt_p; + +my $named_conf = $opt_n; + +use vars qw($named_machine $prefix); +$named_machine = (split(/:/, $named_conf))[0]; +my $pnamed_machine = $named_machine; +$pnamed_machine =~ s/^[\w\-]+\@//; +$prefix = "$spooldir/$pnamed_machine"; +mkdir $prefix unless -d $prefix; + +#iscp("$named_conf","$prefix/named.conf.import"); +scp("$named_conf","$prefix/named.conf.import"); + +## + +$FS::svc_domain::whois_hack=1; + +my $p = Parser->new; +$p->parse_file("$prefix/named.conf.import"); + +print "\nBIND import completed.\n"; + +## + +sub usage { +  die "Usage:\n\n  bind.import -p partnum -n \"user\@machine:/path/to/named.conf\" [ -s ] [ -c chroot_dir ] [ -d ] [ -e ] user\n"; +} + +######## +BEGIN { +   +  package Parser; +  use BIND::Conf_Parser; +  use vars qw(@ISA $named_dir); +  @ISA = qw(BIND::Conf_Parser); + +  $named_dir = 'COULD_NOT_FIND_NAMED_DIRECTORY_TRY_SETTING_-C_OPTION'; +  sub handle_option { +    my($self, $option, $argument) = @_; +    return unless $option eq "directory"; +    $named_dir = $argument; +    #warn "found named dir: $named_dir\n"; +  } +   +  sub handle_zone { +    my($self, $name, $class, $type, $options) = @_; +    return unless $class eq 'in'; +    return if grep { $name eq $_ } (qw( +      . localhost 127.in-addr.arpa 0.in-addr.arpa 255.in-addr.arpa +      0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa +      0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.int +    )); + +    use FS::Record qw(qsearchs); +    use FS::svc_domain; + +    my $domain = +      qsearchs('svc_domain', { 'domain' => $name } ) +      || new FS::svc_domain( { +                               svcpart => $main::domain_svcpart, +                               domain  => $name, +                               action  => 'N', +                           } ); +    unless ( $domain->svcnum ) { +      my $error = $domain->insert; +      die $error if $error; +    } + +    if ( $type eq 'slave' && !$main::opt_s ) { + +      if ( $main::opt_d ) { + +        use Data::Dumper; +        print "$name: ". Dumper($options); + +      } else { + +        foreach my $master ( @{ $options->{masters} } ) { +          my $domain_record = new FS::domain_record( { +            'svcnum'  => $domain->svcnum, +            'reczone' => '@', +            'recaf'   => 'IN', +            'rectype' => '_mstr', +            'recdata' => $master, +          } ); +          my $error = $domain_record->insert; +          die $error if $error; +        } + +      } + +    } elsif ( $type eq 'master' || ( $type eq 'slave' && $main::opt_s ) ) { + +      my $file = $options->{file}; +   +      use File::Basename; +      my $basefile = basename($file); +      my $sourcefile = $file; +      if ( $main::opt_c ) { +        $sourcefile = "$main::opt_c/$sourcefile" if $main::opt_c; +      } else { +        $sourcefile = "$named_dir/$sourcefile" unless $file =~ /^\//; +      } + +      use Net::SCP qw(iscp scp); +      #iscp("$main::named_machine:$sourcefile", +      #     "$main::prefix/$basefile.import"); +      scp("$main::named_machine:$sourcefile", +          "$main::prefix/$basefile.import"); +     +      use DNS::ZoneParse 0.84; +      my $zone = DNS::ZoneParse->new("$main::prefix/$basefile.import"); +     +      my $dump = $zone->dump; + +      if ( $main::opt_d ) { + +        use Data::Dumper; +        print "$name: ". Dumper($dump); + +      } else { +     +        foreach my $rectype ( keys %$dump ) { +          if ( $rectype =~ /^SOA$/i ) { +            my $rec = $dump->{$rectype}; +            $rec->{email} =~ s/\@/\./; +            my $domain_record = new FS::domain_record( { +              'svcnum'  => $domain->svcnum, +              'reczone' => $rec->{origin}, +              'recaf'   => 'IN', +              'rectype' => $rectype, +              'recdata' => +                $rec->{primary}. ' '. $rec->{email}. ' ( '. +               join(' ', map $rec->{$_}, +                             qw( serial refresh retry expire minimumTTL ) ). +               ' )', +            } ); +            my $error = $domain_record->insert; +            die $error if $error; +         } else { +            #die $dump->{$rectype}; + +            my $datasub; +            if ( $rectype =~ /^MX$/i ) { +              $datasub = sub { $_[0]->{priority}. ' '. $_[0]->{host}; }; +            } elsif ( $rectype =~ /^TXT$/i ) { +              $datasub = sub { $_[0]->{text}; }; +            } else { +              $datasub = sub { $_[0]->{host}; }; +            } + +            foreach my $rec ( @{ $dump->{$rectype} } ) { +              my $domain_record = new FS::domain_record( { +                'svcnum'  => $domain->svcnum, +                'reczone' => $rec->{name}, +                'recaf'   => $rec->{class} || 'IN', +                'rectype' => $rectype, +                'recdata' => &{$datasub}($rec), +              } ); +              my $error = $domain_record->insert; +              if ( $error ) { +                warn "$error inserting ". +                     $rec->{name}. ' . '. $domain->domain. "\n"; +                warn Dumper($rec); +                #system('cat',"$main::prefix/$basefile.import"); +                die; +              } +            } +          } +        } + +      } + +    #} else { +    #  die "unrecognized type $type\n"; +    } +     +  } + +} +######### + | 
