source: trunk/tiny-import.pl@ 372

Last change on this file since 372 was 372, checked in by Kris Deugau, 12 years ago

/trunk

Checkpoint adding location/view support. See #10.

  • minor location list template tweak
  • extend importer to deal with locations on records, and location definitions
  • extend exporter to handle locations

Also:

  • minor SQL error-log cleanup (boolean types use 'y'/'n' or 'true'/'false'). See #25, sort of
  • Fix handling of CNAME exports for reverse zones; the records look ugly but there's no simple way to autoconvert them to the template types on import
  • Fix lurking buglet in tabledef update; we're using a 4-char field for locations to allow for legacy uses.
  • Property svn:executable set to *
  • Property svn:keywords set to Date Rev Author Id
File size: 18.4 KB
Line 
1#!/usr/bin/perl
2# dnsadmin shell-based import tool for tinydns flatfiles
3##
4# $Id: tiny-import.pl 372 2012-08-01 22:19:03Z kdeugau $
5# Copyright 2012 Kris Deugau <kdeugau@deepnet.cx>
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU General Public License as published by
9# the Free Software Foundation, either version 3 of the License, or
10# (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU General Public License for more details.
16#
17# You should have received a copy of the GNU General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19##
20
21# WARNING: This is NOT a heavy-duty validator; it is assumed that the data
22# being imported is more or less sane. Only minor structural validation will
23# be done to weed out the most broken records.
24
25use strict;
26use warnings;
27
28use lib '.';
29use DNSDB qw(:ALL);
30
31if (!loadConfig()) {
32 warn "Using default configuration; unable to load custom settings: $DNSDB::errstr";
33}
34
35my $code;
36my ($dbh,$msg) = connectDB($config{dbname}, $config{dbuser}, $config{dbpass}, $config{dbhost});
37initGlobals($dbh) if $dbh;
38
39$dbh->{AutoCommit} = 0;
40$dbh->{RaiseError} = 1;
41
42my %cnt;
43my @deferred;
44my $errstr = '';
45
46foreach my $file (@ARGV) {
47 eval {
48 import(file => $file);
49# import(file => $file, nosoa => 1);
50 $dbh->rollback;
51# $dbh->commit;
52 };
53 if ($@) {
54 print "bleh: $@\n";
55die "die harder: $errstr\n";
56 }
57}
58
59 foreach (keys %cnt) {
60 print " $_ $cnt{$_}\n";
61 }
62
63exit 0;
64
65sub import {
66 our %args = @_;
67 my $flatfile = $args{file};
68 open FLAT, "<$flatfile";
69
70 our $recsth = $dbh->prepare("INSERT INTO records (domain_id,rdns_id,host,type,val,distance,weight,port,ttl,location) ".
71 " VALUES (?,?,?,?,?,?,?,?,?,?)");
72
73 my %deleg;
74
75 while (<FLAT>) {
76 next if /^#/;
77 next if /^\s*$/;
78 chomp;
79 s/\s*$//;
80 recslurp($_);
81 }
82
83 # Try the deferred records again, once.
84 foreach (@deferred) {
85 # print "trying $_ again\n";
86 recslurp($_, 1);
87 }
88
89print scalar(@deferred)." deferred records in $flatfile\n";
90
91 # Sub for various nonstandard types with lots of pure bytes expressed in octal
92 # Takes a tinydns rdata string and count, returns a list of $count bytes as well
93 # as trimming those logical bytes off the front of the rdata string.
94 sub _byteparse {
95 my $src = shift;
96 my $count = shift;
97 my @ret;
98 for (my $i = 0; $i < $count; $i++) {
99 if ($$src =~ /^\\/) {
100 # we should have an octal bit
101 my ($tmp) = ($$src =~ /^(\\\d{3})/);
102 $tmp =~ s/\\/0/;
103 push @ret, oct($tmp);
104 $$src =~ s/^\\\d{3}//;
105 } else {
106 # we seem to have a byte expressed as an ASCII character
107 my ($tmp) = ($$src =~ /^(.)/);
108 push @ret, ord($tmp);
109 $$src =~ s/^.//;
110 }
111 }
112 return @ret;
113 }
114
115 # Convert octal-coded bytes back to something resembling normal characters, general case
116 sub _deoctal {
117 my $targ = shift;
118 while ($$targ =~ /\\(\d{3})/) {
119 my $sub = chr(oct($1));
120 $$targ =~ s/\\$1/$sub/g;
121 }
122 }
123
124 sub _rdata2string {
125 my $rdata = shift;
126 my $tmpout = '';
127 while ($rdata) {
128 my $bytecount = 0;
129 if ($rdata =~ /^\\/) {
130 ($bytecount) = ($rdata =~ /^(\\\d{3})/);
131 $bytecount =~ s/\\/0/;
132 $bytecount = oct($bytecount);
133 $rdata =~ s/^\\\d{3}//;
134 } else {
135 ($bytecount) = ($rdata =~ /^(.)/);
136 $bytecount = ord($bytecount);
137 $rdata =~ s/^.//;
138 }
139 my @tmp = _byteparse(\$rdata, $bytecount);
140 foreach (@tmp) { $tmpout .= chr($_); }
141##fixme: warn or fail on long (>256? >512? >321?) strings
142 }
143 return $tmpout;
144 }
145
146 sub _rdata2hex {
147 my $rdata = shift;
148 my $tmpout = '';
149 while ($rdata) {
150 my $byte = '';
151 if ($rdata =~ /^\\/) {
152 ($byte) = ($rdata =~ /^(\\\d{3})/);
153 $byte =~ s/\\/0/;
154 $tmpout .= sprintf("%0.2x", oct($byte));
155 $rdata =~ s/^\\\d{3}//;
156 } else {
157 ($byte) = ($rdata =~ /^(.)/);
158 $tmpout .= sprintf("%0.2x", ord($byte));
159 $rdata =~ s/^.//;
160 }
161 }
162 return $tmpout;
163 }
164
165
166 sub recslurp {
167 my $rec = shift;
168 my $nodefer = shift || 0;
169
170 $errstr = $rec; # this way at least we have some idea what went <splat>
171
172 if ($rec =~ /^=/) {
173 $cnt{APTR}++;
174
175##fixme: do checks like this for all types
176 if ($rec !~ /^=(?:\*|\\052)?[a-z0-9\._-]+:[\d\.]+:\d*/i) {
177 print "bad A+PTR $rec\n";
178 return;
179 }
180 my ($host,$ip,$ttl,$stamp,$loc) = split /:/, $rec, 5;
181 $host =~ s/^=//;
182 $host =~ s/\.$//;
183 $ttl = 0 if !$ttl;
184 $stamp = '' if !$stamp;
185 $loc = '' if !$loc;
186 $loc = '' if $loc =~ /^:+$/;
187 my $fparent = DNSDB::_hostparent($dbh, $host);
188 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($ip));
189 if ($fparent && $rparent) {
190 $recsth->execute($fparent, $rparent, $host, 65280, $ip, 0, 0, 0, $ttl, $loc);
191 } else {
192 push @deferred, $rec unless $nodefer;
193 # print "$tmporig deferred; can't find both forward and reverse zone parents\n";
194 }
195
196 } elsif ($rec =~ /^C/) {
197 $cnt{CNAME}++;
198
199 my ($host,$targ,$ttl,$stamp,$loc) = split /:/, $rec, 5;
200 $host =~ s/^C//;
201 $host =~ s/\.$//;
202 $host =~ s/^\\052/*/;
203 $ttl = 0 if !$ttl;
204 $stamp = '' if !$stamp;
205 $loc = '' if !$loc;
206 $loc = '' if $loc =~ /^:+$/;
207 if ($host =~ /\.arpa$/) {
208 ($code,$msg) = DNSDB::_zone2cidr($host);
209 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
210 $recsth->execute(0, $rparent, $targ, 5, $msg->addr, 0, 0, 0, $ttl, $loc);
211
212##fixme: automagically convert manually maintained sub-/24 delegations
213# my ($subip, $zone) = split /\./, $targ, 2;
214# ($code, $msg) = DNSDB::_zone2cidr($zone);
215# push @{$deleg{"$msg"}{iplist}}, $subip;
216#print "$msg $subip\n";
217
218 } else {
219 my $fparent = DNSDB::_hostparent($dbh, $host);
220 if ($fparent) {
221 $recsth->execute($fparent, 0, $host, 5, $targ, 0, 0, 0, $ttl, $loc);
222 } else {
223 push @deferred, $rec unless $nodefer;
224 # print "$tmporig deferred; can't find parent zone\n";
225 }
226 }
227
228 } elsif ($rec =~ /^\&/) {
229 $cnt{NS}++;
230
231 my ($zone,$ip,$ns,$ttl,$stamp,$loc) = split /:/, $rec, 6;
232 $zone =~ s/^\&//;
233 $zone =~ s/\.$//;
234 $ns =~ s/\.$//;
235 $ns = "$ns.ns.$zone" if $ns !~ /\./;
236 $ttl = 0 if !$ttl;
237 $stamp = '' if !$stamp;
238 $loc = '' if !$loc;
239 $loc = '' if $loc =~ /^:+$/;
240 if ($zone =~ /\.arpa$/) {
241 ($code,$msg) = DNSDB::_zone2cidr($zone);
242 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >>= ?", undef, ("$msg"));
243##fixme, in concert with the CNAME check for same; automagically
244# create "delegate" record instead for subzone NSes: convert above to use = instead of >>=
245# ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ("$msg"))
246# if !$rparent;
247 if ($rparent) {
248 $recsth->execute(0, $rparent, $ns, 2, $msg, 0, 0, 0, $ttl, $loc);
249 } else {
250 push @deferred, $rec unless $nodefer;
251 }
252 } else {
253 my $fparent = DNSDB::_hostparent($dbh, $zone);
254 if ($fparent) {
255 $recsth->execute($fparent, 0, $zone, 2, $ns, 0, 0, 0, $ttl, $loc);
256 $recsth->execute($fparent, 0, $ns, 2, $ip, 0, 0, 0, $ttl, $loc) if $ip;
257 } else {
258 push @deferred, $rec unless $nodefer;
259 }
260 }
261
262 } elsif ($rec =~ /^\^/) {
263 $cnt{PTR}++;
264
265 my ($rip,$host,$ttl,$stamp,$loc) = split /:/, $rec, 5;
266 $rip =~ s/^\^//;
267 $rip =~ s/\.$//;
268 $ttl = 0 if !$ttl;
269 $stamp = '' if !$stamp;
270 $loc = '' if !$loc;
271 $loc = '' if $loc =~ /^:+$/;
272 my $rparent;
273 if (my ($i, $z) = ($rip =~ /^(\d+)\.(\d+-(?:\d+\.){4}in-addr.arpa)$/) ) {
274 ($code,$msg) = DNSDB::_zone2cidr($z);
275 # Exact matches only, because we're in a sub-/24 delegation
276##fixme: flag the type of delegation (range, subnet-with-dash, subnet-with-slash)
277# somewhere so we can recover it on export. probably best to do that in the revzone data.
278 ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet = ?", undef, ("$msg"));
279 $z =~ s/^[\d-]+//;
280 ($code,$msg) = DNSDB::_zone2cidr("$i.$z"); # Get the actual IP and normalize
281 } else {
282 ($code,$msg) = DNSDB::_zone2cidr($rip);
283 ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ("$msg"));
284 }
285 if ($rparent) {
286 $recsth->execute(0, $rparent, $host, 12, $msg->addr, 0, 0, 0, $ttl, $loc);
287 } else {
288 push @deferred, $rec unless $nodefer;
289 }
290
291 } elsif ($rec =~ /^\+/) {
292 $cnt{A}++;
293
294 my ($host,$ip,$ttl,$stamp,$loc) = split /:/, $rec, 5;
295 $host =~ s/^\+//;
296 $host =~ s/\.$//;
297 $host =~ s/^\\052/*/;
298 $ttl = 0 if !$ttl;
299 $stamp = '' if !$stamp;
300 $loc = '' if !$loc;
301 $loc = '' if $loc =~ /^:+$/;
302
303 my $domid = DNSDB::_hostparent($dbh, $host);
304 if ($domid) {
305 $recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc);
306 } else {
307 push @deferred, $rec unless $nodefer;
308 }
309
310 } elsif ($rec =~ /^Z/) {
311 $cnt{SOA}++;
312
313 my ($zone,$master,$contact,$serial,$refresh,$retry,$expire,$minttl,$ttl,$stamp,$loc) = split /:/, $rec, 11;
314 $zone =~ s/^Z//;
315 $zone =~ s/\.$//;
316 $master =~ s/\.$//;
317 $contact =~ s/\.$//;
318 $ttl = 0 if !$ttl;
319 $stamp = '' if !$stamp;
320 $loc = '' if !$loc;
321 $loc = '' if $loc =~ /^:+$/;
322 if ($zone =~ /\.arpa$/) {
323 ($code,$msg) = DNSDB::_zone2cidr($zone);
324 $dbh->do("INSERT INTO revzones (revnet,group_id,status) VALUES (?,1,1)", undef, ($msg));
325 my ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
326 $recsth->execute(0, $rdns, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
327 } else {
328 $dbh->do("INSERT INTO domains (domain,group_id,status) VALUES (?,1,1)", undef, ($zone));
329 my ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
330 $recsth->execute($domid, 0, "$contact:$master", 6, "$refresh:$retry:$expire:$minttl", 0, 0, 0, $ttl, $loc);
331 }
332
333 } elsif ($rec =~ /^\@/) {
334 $cnt{MX}++;
335
336 my ($zone,$ip,$host,$dist,$ttl,$stamp,$loc) = split /:/, $rec, 7;
337 $zone =~ s/^\@//;
338 $zone =~ s/\.$//;
339 $zone =~ s/^\\052/*/;
340 $host =~ s/\.$//;
341 $host = "$host.mx.$zone" if $host !~ /\./;
342 $ttl = 0 if !$ttl;
343 $stamp = '' if !$stamp;
344 $loc = '' if !$loc;
345 $loc = '' if $loc =~ /^:+$/;
346
347# note we don't check for reverse domains here, because MX records don't make any sense in reverse zones.
348# if this really ever becomes an issue for someone it can be expanded to handle those weirdos
349
350 # allow for subzone MXes, since it's perfectly legitimate to simply stuff it all in a single parent zone
351 my $domid = DNSDB::_hostparent($dbh, $zone);
352 if ($domid) {
353 $recsth->execute($domid, 0, $zone, 15, $host, $dist, 0, 0, $ttl, $loc);
354 $recsth->execute($domid, 0, $host, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
355 } else {
356 push @deferred, $rec unless $nodefer;
357 }
358
359 } elsif ($rec =~ /^'/) {
360 $cnt{TXT}++;
361
362 my ($fqdn, $rdata, $ttl, $stamp, $loc) = split /:/, $rec, 5;
363 $fqdn =~ s/^'//;
364 $fqdn =~ s/^\\052/*/;
365 _deoctal(\$rdata);
366 $ttl = 0 if !$ttl;
367 $stamp = '' if !$stamp;
368 $loc = '' if !$loc;
369 $loc = '' if $loc =~ /^:+$/;
370
371 if ($fqdn =~ /\.arpa$/) {
372 ($code,$msg) = DNSDB::_zone2cidr($fqdn);
373 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
374 $recsth->execute(0, $rparent, $rdata, 16, "$msg", 0, 0, 0, $ttl, $loc);
375 } else {
376 my $domid = DNSDB::_hostparent($dbh, $fqdn);
377 if ($domid) {
378 $recsth->execute($domid, 0, $fqdn, 16, $rdata, 0, 0, 0, $ttl, $loc);
379 } else {
380 push @deferred, $rec unless $nodefer;
381 }
382 }
383
384 } elsif ($rec =~ /^\./) {
385 $cnt{NSASOA}++;
386
387 my ($fqdn, $ip, $ns, $ttl, $stamp, $loc) = split /:/, $rec, 6;
388 $fqdn =~ s/^\.//;
389 $fqdn =~ s/\.$//;
390 $ns =~ s/\.$//;
391 $ns = "$ns.ns.$fqdn" if $ns !~ /\./;
392 $ttl = 0 if !$ttl;
393 $stamp = '' if !$stamp;
394 $loc = '' if !$loc;
395 $loc = '' if $loc =~ /^:+$/;
396
397 if ($fqdn =~ /\.arpa$/) {
398 ($code,$msg) = DNSDB::_zone2cidr($fqdn);
399 my ($rdns) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet = ?", undef, ($msg));
400 if (!$rdns) {
401 $errstr = "adding revzone $msg";
402 $dbh->do("INSERT INTO revzones (revnet,group_id,status) VALUES (?,1,1)", undef, ($msg));
403 ($rdns) = $dbh->selectrow_array("SELECT currval('revzones_rdns_id_seq')");
404# this would probably make a lot more sense to do hostmaster.$config{admindomain}
405 $recsth->execute(0, $rdns, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
406 }
407 $recsth->execute(0, $rdns, $ns, 2, "$msg", 0, 0, 0, $ttl, $loc);
408##fixme: (?) implement full conversion of tinydns . records?
409# -> problem: A record for NS must be added to the appropriate *forward* zone, not the reverse
410#$recsth->execute(0, $rdns, $ns, 1, $ip, 0, 0, 0, $ttl)
411# ... auto-A-record simply does not make sense in reverse zones. Functionally
412# I think it would work, sort of, but it's a nasty mess and anyone hosting reverse
413# zones has names for their nameservers already.
414# Even the auto-nameserver-fqdn comes out... ugly.
415
416 } else {
417 my ($domid) = $dbh->selectrow_array("SELECT domain_id FROM domains WHERE lower(domain) = lower(?)",
418 undef, ($fqdn));
419 if (!$domid) {
420 $errstr = "adding domain $fqdn";
421 $dbh->do("INSERT INTO domains (domain,group_id,status) VALUES (?,1,1)", undef, ($fqdn));
422 ($domid) = $dbh->selectrow_array("SELECT currval('domains_domain_id_seq')");
423 $recsth->execute($domid, 0, "hostmaster.$fqdn:$ns", 6, "16384:2048:1048576:2560", 0, 0, 0, "2560", $loc);
424 }
425 $recsth->execute($domid, 0, $fqdn, 2, $ns, 0, 0, 0, $ttl, $loc);
426 $recsth->execute($domid, 0, $ns, 1, $ip, 0, 0, 0, $ttl, $loc) if $ip;
427 }
428
429
430 } elsif ($rec =~ /^\%/) {
431 $cnt{VIEWS}++;
432
433 # unfortunate that we don't have a guaranteed way to get a description on these. :/
434 my ($loc,$cnet) = split /:/, $rec, 2;
435 $loc =~ s/^\%//;
436 if (my ($iplist) = $dbh->selectrow_array("SELECT iplist FROM locations WHERE location = ?", undef, ($loc))) {
437 if ($cnet) {
438 $iplist .= ",$cnet";
439 $dbh->do("UPDATE locations SET iplist = ? WHERE location = ?", undef, ($iplist, $loc));
440 } else {
441 # hmm. spit out a warning? if we already have entries for $loc, adding a null
442 # entry will almost certainly Do The Wrong Thing(TM)
443 }
444 } else {
445 $cnet = '' if !$cnet; # de-nullify
446 $dbh->do("INSERT INTO locations (location,iplist,description) VALUES (?,?,?)", undef, ($loc, $cnet, $loc));
447 }
448
449 } elsif ($rec =~ /^:/) {
450 $cnt{NCUST}++;
451# Big section. Since tinydns can publish anything you can encode properly, but only provides official
452# recognition and handling for the core common types, this must deal with the leftovers.
453# :fqdn:type:rdata:ttl:time:loc
454
455 my (undef, $fqdn, $type, $rdata, $ttl, $stamp, $loc) = split /:/, $rec, 7;
456 $fqdn =~ s/\.$//;
457 $fqdn =~ s/^\\052/*/;
458 $ttl = 0 if !$ttl;
459 $stamp = '' if !$stamp;
460 $loc = '' if !$loc;
461 $loc = '' if $loc =~ /^:+$/;
462
463 if ($type == 33) {
464 # SRV
465 my ($prio, $weight, $port, $target) = (0,0,0,0);
466
467 my @tmp = _byteparse(\$rdata, 2);
468 $prio = $tmp[0] * 256 + $tmp[1];
469 @tmp = _byteparse(\$rdata, 2);
470 $weight = $tmp[0] * 256 + $tmp[1];
471 @tmp = _byteparse(\$rdata, 2);
472 $port = $tmp[0] * 256 + $tmp[1];
473
474 $rdata =~ s/\\\d{3}/./g;
475 ($target) = ($rdata =~ /^\.(.+)\.$/);
476# hmm. the above *should* work, but What If(TM) we have ASCII-range bytes
477# representing the target's fqdn part length(s)? axfr-get doesn't seem to,
478# probably because dec. 33->63 includes most punctuation and all the numbers
479# while ($rdata =~ /(\\\d{3})/) {
480# my $cnt = $1;
481# $rdata =~ s/^$cnt//;
482# $cnt =~ s/^\\/0/;
483# $cnt = oct($cnt);
484# my ($seg) = ($rdata =~ /^(.{$cnt})/);
485# $target .=
486# }
487
488 my $domid = DNSDB::_hostparent($dbh, $fqdn);
489 if ($domid) {
490 $recsth->execute($domid, 0, $fqdn, 33, $target, $prio, $weight, $port, $ttl, $loc) if $domid;
491 } else {
492 push @deferred, $rec unless $nodefer;
493 }
494
495 } elsif ($type == 28) {
496 # AAAA
497 my @v6;
498
499 for (my $i=0; $i < 8; $i++) {
500 my @tmp = _byteparse(\$rdata, 2);
501 push @v6, sprintf("%0.4x", $tmp[0] * 256 + $tmp[1]);
502 }
503 my $val = NetAddr::IP->new(join(':', @v6));
504
505 my $fparent = DNSDB::_hostparent($dbh, $fqdn);
506 if ($fparent) {
507 $recsth->execute($fparent, 0, $fqdn, 28, $val->addr, 0, 0, 0, $ttl, $loc);
508 } else {
509 push @deferred, $rec unless $nodefer;
510 }
511
512 } elsif ($type == 16) {
513 # TXT
514 my $txtstring = _rdata2string($rdata);
515
516 if ($fqdn =~ /\.arpa$/) {
517 ($code,$msg) = DNSDB::_zone2cidr($fqdn);
518 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
519 if ($rparent) {
520 $recsth->execute(0, $rparent, $txtstring, 16, "$msg", 0, 0, 0, $ttl, $loc);
521 } else {
522 push @deferred, $rec unless $nodefer;
523 }
524 } else {
525 my $domid = DNSDB::_hostparent($dbh, $fqdn);
526 if ($domid) {
527 $recsth->execute($domid, 0, $fqdn, 16, $txtstring, 0, 0, 0, $ttl, $loc);
528 } else {
529 push @deferred, $rec unless $nodefer;
530 }
531 }
532
533 } elsif ($type == 17) {
534 # RP
535 my ($email, $txtrec) = split /\\000/, $rdata;
536 $email =~ s/\\\d{3}/./g;
537 $email =~ s/^\.//;
538 $txtrec =~ s/\\\d{3}/./g;
539 $txtrec =~ s/^\.//;
540
541 # these might actually make sense in a reverse zone... sort of.
542 if ($fqdn =~ /\.arpa$/) {
543 ($code,$msg) = DNSDB::_zone2cidr($fqdn);
544 my ($rparent) = $dbh->selectrow_array("SELECT rdns_id FROM revzones WHERE revnet >> ?", undef, ($msg));
545 if ($rparent) {
546 $recsth->execute(0, $rparent, "$email $txtrec", 17, "$msg", 0, 0, 0, $ttl, $loc);
547 } else {
548 push @deferred, $rec unless $nodefer;
549 }
550 } else {
551 my $domid = DNSDB::_hostparent($dbh, $fqdn);
552 if ($domid) {
553 $recsth->execute($domid, 0, $fqdn, 17, "$email $txtrec", 0, 0, 0, $ttl, $loc);
554 } else {
555 push @deferred, $rec unless $nodefer;
556 }
557 }
558
559 } elsif ($type == 44) {
560 # SSHFP
561 my $sshfp = _byteparse(\$rdata, 1);
562 $sshfp .= " "._byteparse(\$rdata, 1);
563 $sshfp .= " "._rdata2hex($rdata);
564
565 # these do not make sense in a reverse zone, since they're logically attached to an A record
566 my $domid = DNSDB::_hostparent($dbh, $fqdn);
567 if ($domid) {
568 $recsth->execute($domid, 0, $fqdn, 44, $sshfp, 0, 0, 0, $ttl, $loc);
569 } else {
570 push @deferred, $rec unless $nodefer;
571 }
572
573 } else {
574 # ... uhhh, dunno
575 }
576
577 } else {
578 $cnt{other}++;
579 print " $_\n";
580 }
581 }
582
583 close FLAT;
584}
Note: See TracBrowser for help on using the repository browser.