4 # -p: part number for domains
6 # -n: named.conf file (or an include file with zones you want to import),
7 # for example root@ns.isp.com:/var/named/named.conf
10 # -d: dry-run, debug: don't insert any records, just dump debugging output
11 # -e: use existing domains records in Freeside
12 # -s: import slave zones as master. useful if you need to recreate your
13 # primary nameserver from a secondary
14 # -c dir: override patch for downloading zone files (for example, when
15 # downloading zone files from chrooted bind)
17 # need to manually put header in
18 # /usr/local/etc/freeside/export.<datasrc./bind/<machine>/named.conf.HEADER
19 # (or, nowadays, better just to include the file freeside exports)
23 use vars qw($domain_svcpart);
27 #use BIND::Conf_Parser;
28 #use DNS::ZoneParse 0.81;
30 use Net::SCP qw(scp iscp);
32 use FS::UID qw(adminsuidsetup datasrc);
33 use FS::Record qw(qsearch); #qsearchs);
36 use FS::domain_record;
40 use vars qw($opt_p $opt_n $opt_s $opt_c $opt_d $opt_e);
43 my $user = shift or die &usage;
46 $FS::svc_Common::noexport_hack = 1;
47 $FS::domain_record::noserial_hack = 1;
49 use vars qw($spooldir);
50 $spooldir = "/usr/local/etc/freeside/export.". datasrc. "/bind";
51 mkdir $spooldir unless -d $spooldir;
53 $domain_svcpart = $opt_p;
55 my $named_conf = $opt_n;
57 use vars qw($named_machine $prefix);
58 $named_machine = (split(/:/, $named_conf))[0];
59 my $pnamed_machine = $named_machine;
60 $pnamed_machine =~ s/^[\w\-]+\@//;
61 $prefix = "$spooldir/$pnamed_machine";
62 mkdir $prefix unless -d $prefix;
64 #iscp("$named_conf","$prefix/named.conf.import");
65 scp("$named_conf","$prefix/named.conf.import");
69 $FS::svc_domain::whois_hack=1;
72 $p->parse_file("$prefix/named.conf.import");
74 print "\nBIND import completed.\n";
79 die "Usage:\n\n bind.import -p partnum -n \"user\@machine:/path/to/named.conf\" [ -s ] [ -c chroot_dir ] [ -d ] [ -e ] user\n";
86 use BIND::Conf_Parser;
87 use vars qw(@ISA $named_dir);
88 @ISA = qw(BIND::Conf_Parser);
90 $named_dir = 'COULD_NOT_FIND_NAMED_DIRECTORY_TRY_SETTING_-C_OPTION';
92 my($self, $option, $argument) = @_;
93 return unless $option eq "directory";
94 $named_dir = $argument;
95 #warn "found named dir: $named_dir\n";
99 my($self, $name, $class, $type, $options) = @_;
100 return unless $class eq 'in';
101 return if grep { $name eq $_ } (qw(
102 . localhost 127.in-addr.arpa 0.in-addr.arpa 255.in-addr.arpa
103 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
104 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
107 use FS::Record qw(qsearchs);
111 qsearchs('svc_domain', { 'domain' => $name } )
112 || new FS::svc_domain( {
113 svcpart => $main::domain_svcpart,
117 unless ( $domain->svcnum ) {
118 my $error = $domain->insert;
119 die $error if $error;
122 if ( $type eq 'slave' && !$main::opt_s ) {
124 if ( $main::opt_d ) {
127 print "$name: ". Dumper($options);
131 foreach my $master ( @{ $options->{masters} } ) {
132 my $domain_record = new FS::domain_record( {
133 'svcnum' => $domain->svcnum,
136 'rectype' => '_mstr',
137 'recdata' => $master,
139 my $error = $domain_record->insert;
140 die $error if $error;
145 } elsif ( $type eq 'master' || ( $type eq 'slave' && $main::opt_s ) ) {
147 my $file = $options->{file};
150 my $basefile = basename($file);
151 my $sourcefile = $file;
152 if ( $main::opt_c ) {
153 $sourcefile = "$main::opt_c/$sourcefile" if $main::opt_c;
155 $sourcefile = "$named_dir/$sourcefile" unless $file =~ /^\//;
158 use Net::SCP qw(iscp scp);
159 #iscp("$main::named_machine:$sourcefile",
160 # "$main::prefix/$basefile.import");
161 scp("$main::named_machine:$sourcefile",
162 "$main::prefix/$basefile.import");
164 use DNS::ZoneParse 0.84;
165 my $zone = DNS::ZoneParse->new("$main::prefix/$basefile.import");
167 my $dump = $zone->dump;
169 if ( $main::opt_d ) {
172 print "$name: ". Dumper($dump);
176 foreach my $rectype ( keys %$dump ) {
177 if ( $rectype =~ /^SOA$/i ) {
178 my $rec = $dump->{$rectype};
179 $rec->{email} =~ s/\@/\./;
180 my $domain_record = new FS::domain_record( {
181 'svcnum' => $domain->svcnum,
182 'reczone' => $rec->{origin},
184 'rectype' => $rectype,
186 $rec->{primary}. ' '. $rec->{email}. ' ( '.
187 join(' ', map $rec->{$_},
188 qw( serial refresh retry expire minimumTTL ) ).
191 my $error = $domain_record->insert;
192 die $error if $error;
194 #die $dump->{$rectype};
197 if ( $rectype =~ /^MX$/i ) {
198 $datasub = sub { $_[0]->{priority}. ' '. $_[0]->{host}; };
199 } elsif ( $rectype =~ /^TXT$/i ) {
200 $datasub = sub { $_[0]->{text}; };
202 $datasub = sub { $_[0]->{host}; };
205 foreach my $rec ( @{ $dump->{$rectype} } ) {
206 my $domain_record = new FS::domain_record( {
207 'svcnum' => $domain->svcnum,
208 'reczone' => $rec->{name},
209 'recaf' => $rec->{class} || 'IN',
210 'rectype' => $rectype,
211 'recdata' => &{$datasub}($rec),
213 my $error = $domain_record->insert;
215 warn "$error inserting ".
216 $rec->{name}. ' . '. $domain->domain. "\n";
218 #system('cat',"$main::prefix/$basefile.import");
228 # die "unrecognized type $type\n";