Changeset 819


Ignore:
Timestamp:
12/04/20 13:20:46 (3 years ago)
Author:
Kris Deugau
Message:

/trunk

Twelfth sampled iteration of bind-import

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/bind-import

    r818 r819  
    2222use strict;
    2323use warnings;
     24use Getopt::Long;
     25
    2426use Data::Dumper;
    2527
     28##fixme
    2629use lib '.';
    2730use DNSDB;
    2831
    2932my $dnsdb = new DNSDB;
    30 my $doimport = 0;
     33my $doimport = 1;
    3134
    3235#print Dumper(\%reverse_typemap);
     
    3437local $dnsdb->{dbh}->{AutoCommit} = 0;
    3538local $dnsdb->{dbh}->{RaiseError} = 1;
     39
     40# from tiny-import:  arguably can't use -r, -c is irrelevant.  others useful?
     41  # -r  rewrite imported files to comment imported records
     42  # -c  coerce/downconvert A+PTR = records to PTR
     43  # -l  swallow A+PTR as-is
     44  # -m  merge PTR and A/AAAA as possible
     45  # -t  trial mode;  don't commit to DB or actually rewrite flatfile (disables -r)
     46  # -g  import to specified group (name or ID) instead of group 1
    3647
    3748##fixme:  command arguments/flags to set these to alternate values
     
    4253my $serial = time();
    4354
     55my @skipdefs;
     56my $skipfile;
     57
     58GetOptions(
     59        "skip=s" => \@skipdefs,
     60        "skipfile=s" => \$skipfile,
     61        "test|dry-run" => sub { $doimport = 0; },
     62);
     63
     64my $usage = "usage: bind-import [--skip pattern [--skip pattern2 ...]] [--skipfile file]
     65    zonename [zonefile]
     66        --skip   
     67                Specify a string to skip in the records.  If an IP-like string is
     68                used, and the zone is a reverse zone, it will also search for the
     69                octet-reversed form.  Specify multiple times to skip multiple
     70                different record patterns.
     71        --skipfile
     72                A file containing patterns to skip.  Patterns from the file and
     73                any --skip arguments are merged.
     74        zonename
     75                The name of the zone to import.  Required.
     76        zonefile
     77                Specify the zone file as an argument.  If not specified, the zone
     78                data will be read from STDIN.
     79";
     80
    4481my $zname = shift @ARGV;
    4582my $origzone = $zname;
    46 die "usage: bind-import zonename\n" if !$zname;
     83die $usage if !$zname;
     84
     85my $zonefile = shift @ARGV;
     86if(!$zonefile) {
     87  $zonefile = '&STDIN';
     88}
     89
    4790my $rev = 'n';
    4891my $zid;
     92my %foundtypes;
     93
     94if ($skipfile) {
     95  if (-f $skipfile) {
     96    open SKIP, "<$skipfile";
     97    while (<SKIP>) {
     98      push @skipdefs, $_;
     99    }
     100  } else {
     101    warn "skipfile $skipfile requested but it doesn't seem to exist.  Continuing.\n";
     102  }
     103}
     104
     105#sub setreplace {
     106##  print "dbg1: $_[0]\ndbg2: $_[1]\n";
     107##($_[1] eq '' ? $replace = 1 : $replace = $_[1]);
     108#  if ($_[1] eq '') {
     109#    print "no arg value, setting 1\n";
     110#    $replace = 1;
     111#  } else {
     112#    print "arg value $_[1]\n";
     113#    $replace = $_[1];
     114#  }
     115#}
     116
    49117
    50118my %amap;
     
    52120my %cmap;
    53121
     122# wrap all the DB stuff in eval{}, so the entire thing either succeeds or fails.
     123
     124eval {
     125
     126  local $dnsdb->{dbh}->{AutoCommit} = 0;
     127  local $dnsdb->{dbh}->{RaiseError} = 1;
     128
    54129##fixme:  this is wrong, BIND zone files are generally complete and we're adding.  merging records is an entire fridge full of worms.
    55130##fixme:  for import, should arguably check for zone *non*existence
    56 if ($zname =~ /\.arpa\.?$/ || $zname =~ m,^[\d./]+$,) {
    57   $rev = 'y';
    58   $zname = _zone2cidr($zname) if $zname =~ /\.arpa\.?$/;
    59   $zid = $dnsdb->revID($zname,':ANY:');
    60   if ($zid) {
    61 #    die "zone $origzone already present, not merging records\n";
    62 #$zname = new NetAddr::IP $zname;
    63 #    $zname = DNSDB::_ZONE($zname, 'ZONE', 'r', '.').($zname->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
     131  if ($zname =~ /\.arpa\.?$/ || $zname =~ m,^[\d./]+$,) {
     132    $rev = 'y';
     133    $zname = _zone2cidr($zname) if $zname =~ /\.arpa\.?$/;
     134    $zid = $dnsdb->revID($zname,':ANY:');
     135    if ($zid) {
     136      die "zone $origzone already present, not merging records\n";
     137      $zname = new NetAddr::IP $zname;
     138      $zname = DNSDB::_ZONE($zname, 'ZONE', 'r', '.').($zname->{isv6} ? '.ip6.arpa' : '.in-addr.arpa');
     139    }
     140    $zid = $dnsdb->{dbh}->do("INSERT INTO revzones (revnet,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING rnds_id",
     141        undef, ($zname, $group, $status, $location, $serial));
     142
     143  } else {
     144print "dbg: forward zone\n";
     145    $zid = $dnsdb->domainID($zname,':ANY:');
     146    if ($zid) {
     147#      die "zone $origzone already present, not merging records\n";
     148print "dbg: skip add domain\n";
     149    }
     150else {
     151    $zid = $dnsdb->{dbh}->do("INSERT INTO domains (domain,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING domain_id",
     152        undef, ($zname, $group, $status, $location, $serial));
     153}
     154
    64155  }
    65 #  $zid = $dnsdb->{dbh}->do("INSERT INTO revzones (revnet,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING rnds_id",
    66 #                undef, ($zname, $group, $status, $location, $serial));
    67 
    68 } else {
    69   $zid = $dnsdb->domainID($zname,':ANY:');
    70   if ($zid) {
    71 #    die "zone $origzone already present, not merging records\n";
    72   }
    73 #  $zid = $dnsdb->{dbh}->do("INSERT INTO domains (domain,group_id,status,default_location,zserial) VALUES (?,?,?,?,?) RETURNING domain_id",
    74 #                undef, ($zname, $group, $status, $location, $serial));
    75 }
    76 
    77 die "error creating zone stub for $zname: ".$dnsdb->{dbh}->errstr if !$zid;
    78 
    79 
    80 
    81 # still no sane way to expose a human-friendly view tag on the command line.
    82 my $view = shift @ARGV;
    83 $view = '' if !$view;
    84 
    85 ##fixme:  retrieve defttl from SOA record
    86 my $zonettl = 900;
    87 my $defttl = $zonettl;
    88 my $origin = "$zname."; # to append to unqualified names
    89 my %foundtypes;
    90 
    91 # need to spin up a full state machine-ish thing, because BIND zone files are all about context
    92 # see ch4, p56-72 in the grasshopper book
    93 my $prevlabel = '';
    94 my $curlabel = '';
    95 
    96 my $i = 0;
    97 
    98 while (my $rec = <>) {
    99   chomp $rec;
    100   next if $rec =~ /^\s*$/;
    101   next if $rec =~ /^\s*;/;      # comments
    102   next if $rec =~ /^\s*\)/;     # SOA closing (possibly other records too?)
     156
     157  die "error creating zone stub for $zname: ".$dnsdb->{dbh}->errstr if !$zid;
     158
     159
     160##fixme: should probably make this a named argument so it doesn't get confused with the zone filename
     161  # still no sane way to expose a human-friendly view tag on the command line.
     162  my $view = shift @ARGV;
     163  $view = '' if !$view;
     164
     165  ##fixme:  retrieve defttl from SOA record
     166  my $zonettl = 900;
     167  my $defttl = $zonettl;
     168  my $origin = "$zname.";       # to append to unqualified names
     169
     170  # need to spin up a full state machine-ish thing, because BIND zone files are all about context
     171  # see ch4, p56-72 in the grasshopper book
     172  my $prevlabel = '';
     173  my $curlabel = '';
     174
     175  my $i = 0;
     176
     177  open ZONEDATA, "<$zonefile";
     178
     179  while (my $rec = <ZONEDATA>) {
     180    chomp $rec;
     181    next if $rec =~ /^\s*$/;
     182    next if $rec =~ /^\s*;/;    # comments
     183    next if $rec =~ /^\s*\)/;   # SOA closing (possibly other records too?)
    103184                                # arguably should do some more targeted voodoo when parsing the SOA details
    104185
     
    108189  next if /ip.add.re.\d+\s*$/;
    109190
    110 $i++;
    111 #last if $i > 4;
     191  $i++;
     192last if $i > 7;
    112193#print "line $i: ($rec)\n";
    113   if (my ($macro,$mdetail) = ($rec =~ /^\s*\$(TTL|ORIGIN|INCLUDE|GENERATE)\s+(.+)/) ) {
    114     # macro sort of thing;  $TTL and $ORIGIN most common.  $INCLUDE is a thing, expect it to be rare in live use tho
    115     if ($macro eq 'TTL') {
    116       $mdetail =~ s/\s*;.+$//;
    117       if ($mdetail =~ /^\d+$/) {
    118         $defttl = $mdetail;
    119       } else {
    120         warn "invalid \$TTL: $rec\n";
    121       }
    122     } elsif ($macro eq 'ORIGIN') {
     194    if (my ($macro,$mdetail) = ($rec =~ /^\s*\$(TTL|ORIGIN|INCLUDE|GENERATE)\s+(.+)/) ) {
     195      # macro sort of thing;  $TTL and $ORIGIN most common.  $INCLUDE is a thing, expect it to be rare in live use tho
     196      if ($macro eq 'TTL') {
     197        $mdetail =~ s/\s*;.+$//;
     198        if ($mdetail =~ /^\d+$/) {
     199          $defttl = $mdetail;
     200        } else {
     201          warn "invalid \$TTL: $rec\n";
     202        }
     203      } elsif ($macro eq 'ORIGIN') {
    123204##fixme:  going to skip the stupid case of "$ORIGIN com." and the like that lie
    124205# between . and the root domain we were told we're importing;  anyone using such
     
    128209
    129210print "origin ($mdetail)\n";
    130       if ($mdetail =~ /\.$/) {
    131         $origin = $mdetail;
    132       } else {
    133         # append current origin to unqualified origin
    134         $origin = "$mdetail.$origin";
    135       }
     211        if ($mdetail =~ /\.$/) {
     212          $origin = $mdetail;
     213        } else {
     214          # append current origin to unqualified origin
     215          $origin = "$mdetail.$origin";
     216        }
    136217
    137218#      if ($mdetail eq '.' || $mdetail =~ /$zname\.$/ || $zname =~ /$mdetail\.$/) {
     
    142223#      }
    143224
    144     }
    145     elsif ($macro eq 'GENERATE') {
     225      }
     226      elsif ($macro eq 'GENERATE') {
    146227# needs to generate CIDR range(s) as needed to match the start/stop points
    147     }
     228      }
    148229    # not handling $INCLUDE or $GENERATE (altho the latter seems to be mostly a less-flexible version of the template types)
    149     next;
    150   }
    151 
    152   my $origrec = $rec;
     230      next;
     231    }
     232
     233    my $origrec = $rec;
    153234
    154235  # leading whitespace indicates "same label as last record"
    155   if ($rec =~ /^\s/) {
    156     $curlabel = $prevlabel;
     236    if ($rec =~ /^\s/) {
     237      $curlabel = $prevlabel;
    157238print "  found empty label, using previous label\n";
    158   } else {
    159     ($curlabel) = ($rec =~ /^([\w\@_.-]+)\s/);
    160   }
     239    } else {
     240      ($curlabel) = ($rec =~ /^([\w\@_.-]+)\s/);
     241    }
    161242
    162243print "  found '$curlabel'\n";
    163244
    164   # magic name!
    165   $curlabel = "$zname." if $curlabel eq '@';
    166 
    167   # append $ORIGIN if name is not fully qualified.
    168   if ($curlabel !~ /\.$/) {
    169     $curlabel .= ($origin eq '.' ? '.' : ".$origin");
    170   }
     245    # magic name!
     246    $curlabel = "$zname." if $curlabel eq '@';
     247
     248    # append $ORIGIN if name is not fully qualified.
     249    if ($curlabel !~ /\.$/) {
     250      $curlabel .= ($origin eq '.' ? '.' : ".$origin");
     251    }
    171252print "  expanded '$curlabel'\n";
    172253
    173254# hack pthbptt
    174255#$curlabel =~ s/\.\.$/./;
    175   # check for zone scope.  skip bad records.
    176   if ($curlabel !~ /$zname.$/) {
    177     warn "bad record $origrec, maybe bad \$ORIGIN?\n";
     256    # check for zone scope.  skip bad records.
     257    if ($curlabel !~ /$zname.$/) {
     258      warn "bad record $origrec, maybe bad \$ORIGIN?\n";
     259# bweh?  maybe this should die()?
    178260last;
    179     next;
    180   }
    181 
    182   # trim the label, if any
    183   $rec =~ s/^([\w\@_.-]*)\s+//;
     261      next;
     262    }
     263
     264    # trim the label, if any
     265    $rec =~ s/^([\w\@_.-]*)\s+//;
    184266
    185267#  # records must begin in the first column, no leading whitespace
     
    219301
    220302
    221   my $nc = 0;
    222   my $class = 'IN';
    223   my $type;
    224   my $ttl;
    225   my $distance;
    226   my $weight;
    227   my $port;
    228   my $badrec;
    229   my $curatom = 'class';
    230 
    231   eval {
    232     for (; $nc < 3; $nc++) {
    233       my ($atom) = ($rec =~ /^([\w\d.]+)\s/);
    234       # should be safe?
    235       last if !$atom;
    236       last if $type;
     303    my $nc = 0;
     304    my $class = 'IN';
     305    my $type;
     306    my $ttl;
     307    my $distance;
     308    my $weight;
     309    my $port;
     310    my $badrec;
     311    my $curatom = 'class';
     312
     313    # unpack the class, TTL, and type
     314    eval {
     315      for (; $nc < 3; $nc++) {
     316        my ($atom) = ($rec =~ /^([\w\d.]+)\s/);
     317        # should be safe?
     318        last if !$atom;
     319        last if $type;
    237320#print "nc:$nc: $atom\n";
    238       if ($atom =~ /^\d+$/) {
    239         if (defined($ttl)) {
    240           die "bad record ($origrec)\n";
    241 #          warn "bad record ($origrec)\n";
    242 #          $badrec = 1;
    243 #          last;
    244         } else {
    245           if ($curatom ne 'class' && $curatom ne 'ttl') {
     321        if ($atom =~ /^\d+$/) {
     322          if (defined($ttl)) {
    246323            die "bad record ($origrec)\n";
    247324#            warn "bad record ($origrec)\n";
    248325#            $badrec = 1;
    249326#            last;
     327          } else {
     328            if ($curatom ne 'class' && $curatom ne 'ttl') {
     329              die "bad record ($origrec)\n";
     330#              warn "bad record ($origrec)\n";
     331#              $badrec = 1;
     332#              last;
     333            }
     334            $curatom = 'ttl';
     335            $ttl = $atom;
    250336          }
    251           $curatom = 'ttl';
    252           $ttl = $atom;
    253337        }
    254       }
    255 
    256       elsif ($atom =~ /^IN|CS|CH|HS$/) {
     338
     339        elsif ($atom =~ /^IN|CS|CH|HS$/) {
    257340#print "a$nc: d2: atom [$atom]\n        $rec\n" if $i == $debugid;
    258         if ($atom =~ /CS|CH|HS/) {
    259           die "unsupported class $atom in record ($origrec)\n";
    260 #          warn "unsupported class $atom in record ($origrec)\n";
    261 #          $badrec = 1;
    262 #          last;
     341          if ($atom =~ /CS|CH|HS/) {
     342            die "unsupported class $atom in record ($origrec)\n";
     343#            warn "unsupported class $atom in record ($origrec)\n";
     344#            $badrec = 1;
     345#            last;
     346          }
     347          $curatom = 'class';
     348          $class = $atom;
    263349        }
    264         $curatom = 'class';
    265         $class = $atom;
    266       }
    267 
    268       elsif ($atom =~ /^[A-Z]+/) {
     350
     351        elsif ($atom =~ /^[A-Z]+/) {
    269352#      print "dbg: type $atom\n";
    270         if ($reverse_typemap{$atom}) {
    271           $type = $atom;
    272         } else {
    273           die "unknown type $atom in record ($origrec)\n";
     353          if ($reverse_typemap{$atom}) {
     354            $type = $atom;
     355          } else {
     356            die "unknown type $atom in record ($origrec)\n";
     357          }
    274358        }
    275       }
    276       $rec =~ s/^$atom\s*//;
    277     }
    278   };
    279   if ($@) {
    280     warn $@;
    281     next;
    282   }
     359        $rec =~ s/^$atom\s*//;
     360      }
     361    }; # record class/type/TTL parse
     362    if ($@) {
     363      warn $@;
     364      next;
     365    }
    283366
    284367##todo:  BIND conflates a repeated label with repeating the TTL too.  Matter of opinion whether that's really correct or not.
    285   # set default TTL here so we can detect a TTL in the loop above
    286   $ttl = $defttl if !defined($ttl);
     368    # set default TTL here so we can detect a TTL in the loop above
     369    $ttl = $defttl if !defined($ttl);
    287370
    288371#next if $badrec;
    289372
    290 
    291 ##fixme:  drop curlabel?  not sure it's needed
    292 #$curlabel = $name;
    293 $prevlabel = $curlabel;
    294 
     373    $prevlabel = $curlabel;
    295374
    296375
     
    326405
    327406
    328   my $itype = $reverse_typemap{$type};
    329   my $rdata = $rec;
     407    my $itype = $reverse_typemap{$type};
     408    my $rdata = $rec;
    330409
    331410  # SOA is the only type that may span multiple lines.  Probably.  Note even AXFRed zones write multiline SOA records:
     
    348427  #$ORIGIN example.invalid.
    349428  #foo                     A       192.168.16.45
    350 $foundtypes{$type}++;
     429  $foundtypes{$type}++;
    351430
    352431##fixme:  strip trailing . here?  dnsadmin's normalized internal format omits it, some validation fails or may go funky
    353432
    354   if ($type eq 'SOA') {
    355     my ($ns, $adminmail) = ($rdata =~ /([\w.]+)\s+([\w.]+)\s+\(/);
    356     die "Can't parse gibberish SOAish record: $rec\n" if !$ns;
    357     $rdata =~ s/([\w.]+)\s+([\w.]+)\s+\(\s*//;
    358 
    359     # There are probably more efficient ways to do this but the SOA record
    360     # format is essentially character based, not line-based.
    361     # In theory the SOA serial etc may be spread over up to 5 lines, in any combination.
    362 
    363     # Parse fields from $rdata if present
    364     my @soabits;
    365     my @soafirst = split /\s+/, $rdata;
    366     while (my $f = shift @soafirst) {
    367       last if $f !~ /^\d/;
    368       push @soabits, $f;
    369     }
    370 
    371     # Read more lines if we don't have enough SOA fields filled
    372     while (scalar(@soabits) < 5) {
    373       my $tmp = <>;
    374       $tmp =~ s/^\s*//;
    375       my @tmpsoa = split /\s+/, $tmp;
    376       while (my $f = shift @tmpsoa) {
     433    if ($type eq 'SOA') {
     434      my ($ns, $adminmail) = ($rdata =~ /([\w.]+)\s+([\w.]+)\s+\(/);
     435      die "Can't parse gibberish SOAish record: $rec\n" if !$ns;
     436      $rdata =~ s/([\w.]+)\s+([\w.]+)\s+\(\s*//;
     437
     438      # There are probably more efficient ways to do this but the SOA record
     439      # format is essentially character based, not line-based.
     440      # In theory the SOA serial etc may be spread over up to 5 lines, in any combination.
     441
     442      # Parse fields from $rdata if present
     443      my @soabits;
     444      my @soafirst = split /\s+/, $rdata;
     445      while (my $f = shift @soafirst) {
    377446        last if $f !~ /^\d/;
    378         push @soabits, $f; 
    379       }
    380       if (scalar(@soabits) == 5) {
    381         last;
    382       }
    383     }
    384 #  $dnsdb->{dbh}->do("UPDATE [zonetable] SET serial = ? WHERE [idfield] = ?");
     447        push @soabits, $f;
     448      }
     449
     450      # Read more lines if we don't have enough SOA fields filled
     451      while (scalar(@soabits) < 5) {
     452        my $tmp = <ZONEDATA>;
     453        $tmp =~ s/^\s*//;
     454        my @tmpsoa = split /\s+/, $tmp;
     455        while (my $f = shift @tmpsoa) {
     456          last if $f !~ /^\d/;
     457          push @soabits, $f; 
     458        }
     459        if (scalar(@soabits) == 5) {
     460          last;
     461        }
     462      }
     463      my @soavals = ($zid, "$adminmail:$ns", 6, join(':', @soabits), $ttl, $location);
     464# host = $adminmail:$ns
     465# val = join(':', @soabits);
     466
     467      if ($rev eq 'y') {
     468        $dnsdb->{dbh}->do("UPDATE revzones SET zserial = ? WHERE rdns_id = ?", undef, $soabits[0], $zid);
     469        $dnsdb->{dbh}->do("INSERT INTO records (rdns_id,host,type,val,ttl,location) VALUES (?,?,?,?,?,?)", undef, @soavals);
     470      } else {
     471        $dnsdb->{dbh}->do("UPDATE domains SET zserial = ? WHERE domain_id = ?", undef, $soabits[0], $zid);
     472        $dnsdb->{dbh}->do("INSERT INTO records (domain_id,host,type,val,ttl,location) VALUES (?,?,?,?,?,?)", undef, @soavals);
     473      }
    385474#  $dnsdb->{dbh}->do("INSERT INTO records () VALUES ()");
    386475#  next;
    387476#Zfqdn:mname:rname:ser:ref:ret:exp:min:ttl:timestamp:lo
    388477#print "Z$zname:$ns:$adminmail:$soabits[0]:$soabits[1]:$soabits[2]:$soabits[3]:$soabits[4]:$ttl\n";
    389   } # SOA
    390 
    391 
    392   # we're using DNSDB::addrec(), so we'll skip detailed validation of other records.  Most won't need further breakdown
    393 
    394   elsif ($type eq 'A') {
     478    } # SOA
     479
     480
     481    # we're using DNSDB::addrec(), so we'll skip detailed validation of other records.  Most won't need further breakdown
     482
     483    elsif ($type eq 'A') {
    395484#print "+$curlabel:$rdata:$ttl\n";
    396   }
    397 
    398   elsif ($type eq 'NS') {
     485    }
     486
     487    elsif ($type eq 'NS') {
    399488#print "\&$curlabel::$rdata:$ttl\n";
    400   }
    401 
    402   elsif ($type eq 'CNAME') {
     489    }
     490
     491    elsif ($type eq 'CNAME') {
    403492#print "C$curlabel:$rdata:$ttl\n";
    404   }
    405 
    406   elsif ($type eq 'PTR') {
    407   }
    408 
    409   elsif ($type eq 'MX') {
    410     ($distance) = ($rdata =~ /^(\d+)\s+/);
    411     if (!defined($distance)) {
    412       warn "malformed MX record: $origrec, skipping\n";
    413       next;
    414     }
    415     $rdata =~ s/^\d+\s+//;
    416   }
    417 
    418   elsif ($type eq 'TXT') {
    419     # Quotes may arguably be syntactically required, but they're not actually part of the record data
    420     $rdata =~ s/^"//;
    421     $rdata =~ s/"$//;
     493    }
     494
     495    elsif ($type eq 'PTR') {
     496    }
     497
     498    elsif ($type eq 'MX') {
     499      ($distance) = ($rdata =~ /^(\d+)\s+/);
     500      if (!defined($distance)) {
     501        warn "malformed MX record: $origrec, skipping\n";
     502        next;
     503      }
     504      $rdata =~ s/^\d+\s+//;
     505    }
     506
     507    elsif ($type eq 'TXT') {
     508      # Quotes may arguably be syntactically required, but they're not actually part of the record data
     509      $rdata =~ s/^"//;
     510      $rdata =~ s/"$//;
    422511#print "'$curlabel:$rdata:$ttl\n";
    423   }
    424 
    425   elsif ($type eq 'RP') {
    426   }
    427 
    428   elsif ($type eq 'AAAA') {
    429   }
    430 
    431   elsif ($type eq 'SRV') {
    432     ($distance, $weight, $port) = ($rdata =~ /^(\d+)\s+(\d+)\s+(\d+)\s+/);
    433     if ( !defined($distance) || !defined($weight) || !defined($port) ) {
    434       warn "malformed SRV record: $origrec, skipping\n";
    435       next;
    436     }
    437     $rdata =~ s/^\d+\s+\d+\s+\d+\s+//;
    438   }
    439 
    440   # basically a dedicated clone of TXT, not sure anything actually looks up type SPF.
    441   # BIND autogenerates them from SPF TXT records.
    442   elsif ($type eq 'SPF') {
    443     # Quotes may arguably be syntactically required, but they're not actually part of the record data
    444     $rdata =~ s/^"//;
    445     $rdata =~ s/"$//;
    446   }
     512    }
     513
     514    elsif ($type eq 'RP') {
     515    }
     516
     517    elsif ($type eq 'AAAA') {
     518    }
     519
     520    elsif ($type eq 'SRV') {
     521      ($distance, $weight, $port) = ($rdata =~ /^(\d+)\s+(\d+)\s+(\d+)\s+/);
     522      if ( !defined($distance) || !defined($weight) || !defined($port) ) {
     523        warn "malformed SRV record: $origrec, skipping\n";
     524        next;
     525      }
     526      $rdata =~ s/^\d+\s+\d+\s+\d+\s+//;
     527    }
     528
     529    # basically a dedicated clone of TXT, not sure anything actually looks up type SPF.
     530    # BIND autogenerates them from SPF TXT records.
     531    elsif ($type eq 'SPF') {
     532      # Quotes may arguably be syntactically required, but they're not actually part of the record data
     533      $rdata =~ s/^"//;
     534      $rdata =~ s/"$//;
     535    }
    447536
    448537#  elsif ($type eq 'TXT') {
    449538#  elsif ($type eq 'TXT') {
    450539
    451   else {
    452     warn "unsupported type $type, may not import correctly\n";
    453   }
     540    else {
     541      warn "unsupported type $type, may not import correctly\n";
     542    }
    454543
    455544no warnings qw(uninitialized);
     
    458547#;imap   IN      900     CNAME   deepnet.cx.
    459548##fixme:  not sure how to handle the case where someone leaves off the class.
    460   if ($doimport) {
    461     my ($code, $msg);
    462     if ($rev eq 'n') {
    463       ($code,$msg) = $dnsdb->addRec('n', $rev, $zid, \$curlabel, \$itype, \$rdata, $ttl,
    464         $location, undef, undef, $distance, $weight, $port);
    465     } else {
    466       ($code,$msg) = $dnsdb->addRec('y', $rev, $zid, \$rdata, \$itype, \$curlabel, $ttl,
    467         $location, undef, undef, $distance, $weight, $port);
    468     }
    469     print "$code: $msg\n";
     549    if ($doimport) {
     550      my ($code, $msg);
     551      if ($rev eq 'n') {
     552        ($code,$msg) = $dnsdb->addRec('n', $rev, $zid, \$curlabel, \$itype, \$rdata, $ttl,
     553          $location, undef, undef, $distance, $weight, $port);
     554      } else {
     555        ($code,$msg) = $dnsdb->addRec('y', $rev, $zid, \$rdata, \$itype, \$curlabel, $ttl,
     556          $location, undef, undef, $distance, $weight, $port);
     557      }
     558      print "$code: $msg\n";
     559    }
     560#  $i++;
    470561  }
    471 #  $i++;
     562
     563};
     564if ($@) {
     565  warn "Error parsing zonefile: $@\n";
     566  $dnsdb->{dbh}->rollback;
     567  exit;
    472568}
    473 
    474569
    475570#print Dumper \%amap;
     
    497592#}
    498593
    499 $dnsdb->{dbh}->rollback;
     594##fixme: might not be sane, addRec() above does a commit() internally.
     595#$dnsdb->{dbh}->rollback;
     596$dnsdb->{dbh}->commit;
    500597
    501598foreach my $t (keys %foundtypes) {
Note: See TracChangeset for help on using the changeset viewer.