commit d06a79e3538961fd9652bfc1f089a22ee6b04d68 Author: Christoph Date: Tue Feb 21 02:35:57 2017 +0100 Initial import diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a149b6f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/BAK/* diff --git a/analyze_dns_datafile.pl b/analyze_dns_datafile.pl new file mode 100755 index 0000000..242d160 --- /dev/null +++ b/analyze_dns_datafile.pl @@ -0,0 +1,459 @@ +#!/usr/bin/perl -w + +use strict; +use Fcntl qw(:DEFAULT :flock); + +use Symbol qw(gensym); +use Getopt::Std; +use IO::File; +use File::Basename; +use Cwd; + +use vars qw/$opt_a $opt_b $opt_d $opt_e $opt_h $opt_m $opt_o $opt_q/; + + +my $zonefile_suffixi_default = "file"; +my $outfile_default = "data_dns"; + +my $out_data_file = "nsdata.txt"; + +## - hashes to store the records at all, but also +## - domains, maildomains and the defined hosts +## - +my %doms = (); +my %maildoms = (); +my %hosts = () ; +my %records = () ; + + +## - filehandle +## - +my $fh = new IO::File ; + + +getopts('ab:d:e:hmo:q') || &usage(); +&usage if defined $opt_h ; + +my $i; +if (! defined $opt_q) { + print "\n command invoked: $0"; + foreach $i (@ARGV) { + print " $i"; + } + print "\n\n"; +} + +my $backup = defined($opt_b) ? $opt_b : 1; +if ( $backup != 1 && $backup != 0 ) { + print "\n wrong value for flag -b : $opt_b"; + &usage; +} + + +exit ( &main(@ARGV) ); + +sub main { + + my $infile = shift || return usage(); + + + -f $infile or die "$infile: $!"; + + my $base_infile = basename($infile); + + + my ($line, $filename); + my ( @lines, @data_file_lines, @single_file_lines ); + my ( @domains, @maildomains, @hostlist, @records ); + + my ( $extension, $outdir, $outfile, $multiple_files, $add_files ); + + ## - look at the programm parameters + ## - + $extension = defined($opt_e) ? $opt_e : $zonefile_suffixi_default; + $outdir = defined($opt_d) ? $opt_d : "./"; + + + ## - like to work with the realpath + ## - + $outdir = Cwd::abs_path($outdir); + ## $outdir =~ s#^(.*)/$#$1#; + + + $outfile = defined($opt_o) ? $opt_o : $outfile_default; + $outfile = $outdir . "/" . $outfile; + $multiple_files = defined($opt_m) ? 1 : 0; + $add_files = defined($opt_a) ? 1 : 0; + + ## - Datei einlesen + ## - + if ( $fh->open($infile) ) { + flock( $fh, LOCK_SH ); + chomp (@lines = <$fh>); + flock( $fh, LOCK_UN ); + $fh->close(); + } else { + die "can't open $! for read"; + } + + + ## oder so.. + ## - + ## open( $fh ,$infile ) or die "can't open $! for read" ; + ## flock( $fh, LOCK_SH ); + ## @lines = <$fh>; + ## flock( $fh, LOCK_UN ); + ## close ( $fh ); + + ## - sichere original file + ## - + &write_file($outdir . "/" . $base_infile,@lines); + + ## - first we push into hashes, so we can sort + ## - afterwords + ## - + + foreach (@lines) { + + ## chomp ; + + ## - ignore emty lines + ## - + next if /^\s*$/o ; + + ## - ignore comments + ## - + next if /^#/o ; + + $records{$_} = 1 ; + if ( /^([\.|\&|Z])([^:]*)(.*)$/o ) { + $doms{$2} = 1 ; + } + + ## - maildomain ? + ## - + if ( /^(\@)([^:]*)(.*)/o) { + $maildoms{$2} = 1; + } + + ## - host definition ? + ## - + if ( /^(\+)([^:]*)(.*)/o) { + $hosts{$2} = 1; + } + } + + + ## - Now sort and put into the considered arrays + ## - + @domains = sort ( keys %doms ) ; + @maildomains = sort ( keys %maildoms ) ; + @hostlist = sort ( keys %hosts ) ; + @records = sort ( sort_records keys %records); + + + + ## - schreibe domainliste, maildomainliste, hostliste, records + ## - + if ( $add_files ) { + &write_file($outdir . "/domains.lst",@domains); + &write_file($outdir . "/maildomains.lst",@maildomains); + &write_file($outdir . "/hostlist.lst",@hostlist); + &write_file($outdir . "/records.lst",@records); + } + + my $_domain =""; + my $_type; + my $_filename = 0; + foreach ( @records ) { + + /(.)([^:]+).*/o ; + if ( $_domain eq get_domain($2) ) { + if ( $_type ne $1 ) { + if ( $multiple_files ) { + push ( @single_file_lines, get_record_comment($1) ); + } else { + push ( @data_file_lines, get_record_comment($1) ); + } + } + if ( $multiple_files ) { + push ( @single_file_lines, $_ ); + } else { + push ( @data_file_lines, $_ ); + } + } else { + &write_file($filename,@single_file_lines) if ($filename); + @single_file_lines = (); + $_type = ""; + $_domain = get_domain($2); + + if ( $multiple_files ) { + $filename = $outdir . "/" . $_domain . ".file"; + push ( @single_file_lines, "## - domain: $_domain"); + push ( @single_file_lines, "## - "); + push ( @single_file_lines, get_record_comment($1) ); + push ( @single_file_lines, $_ ); + } else { + push ( @data_file_lines, "\n" ); + push ( @data_file_lines, "## - domain: $_domain"); + push ( @data_file_lines, "## - "); + push ( @data_file_lines, get_record_comment($1) ); + push ( @data_file_lines, $_ ); + } + + + } + $_type = $1; + + } + + if ( $multiple_files ) { + ## - letztes file muss noch geschrieben werdem + ## - + &write_file($filename, @single_file_lines); + } else { + ## - schreibe alles in ein file + ## - + &write_file($outfile, @data_file_lines); + } + + exit 0 +} + + +sub get_domain { + + my $record = shift ; + + if ( $doms{$record} ) { + return $record ; + } else { + while ( $record =~ /([^\.]*).(.*)/o ) { + if ( $doms{$2} ) { + return $2; + } + $record = $2; + } + } + + return 1 ; + +} + + +sub get_record_comment { + my $directive_type = shift; + my $comment; + + SWITCH : { + + $1 eq "Z" and $comment = "## - SOA" , last SWITCH; + $1 eq "." and $comment = "## - SOA, NS, A" , last SWITCH; + $1 eq "&" and $comment = "## - NS, A" , last SWITCH; + $1 eq "@" and $comment = "## - MX, A" , last SWITCH; + $1 eq "=" and $comment = "## - A, PTR" , last SWITCH; + $1 eq "+" and $comment = "## - A" , last SWITCH; + $1 eq "C" and $comment = "## - CNAME" , last SWITCH; + $1 eq "^" and $comment = "## - PTR" , last SWITCH; + $1 eq "'" and $comment = "## - TEXT" , last SWITCH; + $1 eq "3" and $comment = "## - AAAA" , last SWITCH; + $1 eq "6" and $comment = "## - AAAA, PTR" , last SWITCH; + $comment = "## - unknown record"; + } + return $comment; + +} + + +# Datei schreiben +# +sub write_file { + + my $outfile = shift ; + my @lines = @_ ; + + backup($outfile) if ( -f $outfile ); + + if (! defined $opt_q) { + print "\twrite $outfile ..\n"; + } + + $fh = new IO::File "> $outfile"; + if (defined $fh) { + foreach (@lines) { + print $fh $_ . "\n" ; + } + $fh->close(); + } + + ## - oder auch so.. + ## - + ## open ( $fh , "> $outfile") or die "can't open $! for write" ; + ## print $fh @lines ; + ## close ($fh); + +} + +# +# - backup +# +sub backup { + + my $filename = shift ; + + # Sicherungskopie erstellen + # + if ($backup) { + OUTER: for ( my $i = 0 ; $i < 10 ; $i++ ) { + for ( my $j = 0 ; $j < 10 ; $j++ ) { + my $backupfile = $filename . ".$i$j" ; + if ( -f $backupfile + || -d $backupfile + || -l $backupfile + || -p $backupfile + || -c $backupfile + || -b $backupfile + || -S $backupfile ) { + next ; + } else { + my $retval = system( "cp -f $filename $backupfile") ; + if ($retval != 0) { + die "can't store backupfile $backupfile" + } + if (! defined $opt_q) { + print "\n\tbackupfile stored in $backupfile\n"; + } + last OUTER ; + } + } + } # ende OUTER : for ( ... + } # ende if +} # end backup() + +sub sort_records { + + my ( $rval1, $rval2, $domain_a, $domain_b, $directive_a, $directive_b ); + + + $a =~ /(.)([^:]+).*/; + + ## - get directive + ## - + SWITCH : { + + $1 eq "Z" and $directive_a = 10 , last SWITCH; + $1 eq "." and $directive_a = 20 , last SWITCH; + $1 eq "&" and $directive_a = 30 , last SWITCH; + $1 eq "@" and $directive_a = 40 , last SWITCH; + $1 eq "=" and $directive_a = 50 , last SWITCH; + $1 eq "+" and $directive_a = 60 , last SWITCH; + $1 eq "C" and $directive_a = 70 , last SWITCH; + $1 eq "^" and $directive_a = 80 , last SWITCH; + $1 eq "'" and $directive_a = 90 , last SWITCH; + $1 eq "3" and $directive_a = 100, last SWITCH; + $1 eq "6" and $directive_a = 110, last SWITCH; + $directive_a = 999; + } + + ## - get domain.. + ## - + $domain_a = get_domain($2); + + $b =~ /(.)([^:]+).*/; + + ## - get directive + ## - + SWITCH : { + + $1 eq "Z" and $directive_b = 10 , last SWITCH; + $1 eq "." and $directive_b = 20 , last SWITCH; + $1 eq "&" and $directive_b = 30 , last SWITCH; + $1 eq "@" and $directive_b = 40 , last SWITCH; + $1 eq "=" and $directive_b = 50 , last SWITCH; + $1 eq "+" and $directive_b = 60 , last SWITCH; + $1 eq "C" and $directive_b = 70 , last SWITCH; + $1 eq "^" and $directive_b = 80 , last SWITCH; + $1 eq "'" and $directive_b = 90 , last SWITCH; + $1 eq "3" and $directive_b = 100, last SWITCH; + $1 eq "6" and $directive_b = 110, last SWITCH; + $directive_b = 999; + } + + ## - get domain.. + ## - + $domain_b = get_domain($2); + + $rval1 = $domain_a cmp $domain_b ; + + + if ( $rval1 == 0 ) { + $rval2 = $directive_a <=> $directive_b; + if ( $rval2 == 0 ) { + return $a cmp $b; + } else { + return $rval2; + } + } else { + return $rval1; + } + +} + + + +# +# - usage +# +sub usage { + my $file = basename($0); + $file =~ s#.*/([^/]+)$#$1# ; + + print < + +This script concatinates all zonefiles with a certain fileextension +of a given directory. + +This script takes all directives from a given djb tinydns-data-file, +sorts them and put the sortet list back into one data-file or, if +option "m" is set into one file for each domain, named by the concerning +domain. + +A copy of the (original) inputfile will be written out in . + + +Control Options: + + -a The following addition files be written: + /domains.lst.......: alphabetical list of domains + /maildomains.lst...: alphabetical list of domains + with MX entry + /hostlist.lst......: alphabetical list of all + hostentries (A - Record) + /records.lst.......: all records sorted by domain but + without any comment or emty line + + -b <0|1> a value of "1" means: befor writing a file backup existing one; + dont backup if "0". default value is "1" + + -d directory where the outfile(s) are written. defaults to + working directory + + -e write data-files with extension . defaults to + "$zonefile_suffixi_default". only affected if option -m is set + + -h prints this helpcontents + + -m write one file for each domain + + -o name of outputfile. defaults to "$outfile_default". only + affect if not -m is set + + -q silent output + + +ENDE + + exit 1 ; +} diff --git a/concatenate_dns_datafiles.pl b/concatenate_dns_datafiles.pl new file mode 100755 index 0000000..14774f9 --- /dev/null +++ b/concatenate_dns_datafiles.pl @@ -0,0 +1,169 @@ +#!/usr/bin/perl + +use strict; + +use Symbol; +use Getopt::Std; +use Cwd; +use vars qw/$opt_e $opt_h $opt_o $opt_q $opt_r $opt_R $opt_X/; + + +my $zonefile_suffixi_default = "file"; +my $outfile_default = "data_dns"; + +my ( @lines ); +my ( $extension, $dirdepth, $recursiv, $excl_dir, $outfile ); + +my $i ; + +getopts('e:ho:qrR:X:') || &usage(); +&usage if defined $opt_h ; + + +if (! defined $opt_q) { + print "\n command invoked: $0"; + foreach $i (@ARGV) { + print " $i"; + } + print "\n\n"; +} + +exit ( &main(@ARGV) ); + +## - main method +## +sub main { + + my $rootdir = shift || return usage(); + $rootdir =~ s#/$## ; + + ## - like to work with the realpath + ## - + $rootdir = Cwd::abs_path($rootdir); + + ## - look at the programm parameters + ## - + $extension = defined($opt_e) ? $opt_e : $zonefile_suffixi_default; + $outfile = defined($opt_o) ? $opt_o : $outfile_default; + $dirdepth = defined($opt_R) ? $opt_R : -1; + if ($dirdepth > 0 ) { + $recursiv = 1 ; + } else { + $recursiv = defined($opt_r) ? 1 : 0; + } + $excl_dir = defined($opt_X) ? $opt_X : ""; + + &traverse_dir($rootdir,0); + + &write_file("data_dns",@lines); + exit (0) + +} + +## - traverse_dir +## - +sub traverse_dir { + + my $dir = shift ; + my $dircount = shift ; + + my $dirh = gensym ; + my $filename ; + my @dir ; + + opendir($dirh , $dir) || die "can't open $dir"; + @dir=readdir($dirh); + @dir = sort(@dir); + closedir($dirh); + #while ( defined ( $filename = readdir($dirh) ) ) { + foreach ( @dir ) { + $filename = $_; + + next if $filename eq "." || $filename eq ".." ; + ## - no system files + next if ( $filename =~ /^\./ ) ; + my $pathname = $dir . "/" . $filename ; + next if -l $pathname ; + next if ( -d $pathname && $filename eq $excl_dir ) ; + if ( -d $pathname && $recursiv + && ($dirdepth == -1 || $dircount < $dirdepth) + ) { + &traverse_dir($pathname, ($dircount + 1 )) ; + next ; + } + next if not -T $pathname ; + next unless -f $pathname; + if ($extension ne "") { + next if not ( $pathname =~ /$extension$/ ) ; + } + + open (CFG, $pathname ) or die "open file $pathname: $!\n"; + while ( ) { + push(@lines , $_); + } + close CFG; + push (@lines, "\n\n"); + } + + ## - write out concatinated file + ## - + &write_file($outfile, @lines); + + return 0; +} # ende traverse_dir + + + +# Datei schreiben +# +sub write_file { + + my $outfile = shift ; + my @lines = @_ ; + + open ( FH , "> $outfile") or die "can't open $! for write" ; + print FH @lines ; + close (FH); + +} + + +# +# - usage +# +sub usage { + my $file = $0; + $file =~ s#.*/([^/]+)$#$1# ; + + print < + +This script concatinates all zonefiles with a certain fileextension +of a given directory. + + +Control Options: + + -e concatinate files with extension ext + defaults to "$zonefile_suffixi_default" + + -h prints this helpcontents + + -o name of outputfile. defaults to "$outfile_default" in the + working directory + + -q silent output + + -r recursivly + + -R NUM concatinate files recursivly with directorydepth = "NUM" + + + -X dir excluding replacing directories named dir + +ENDE + + exit 1 ; +} + diff --git a/convert_tinydns_to_bind.pl b/convert_tinydns_to_bind.pl new file mode 100755 index 0000000..9fbef44 --- /dev/null +++ b/convert_tinydns_to_bind.pl @@ -0,0 +1,687 @@ +#!/usr/bin/perl -w + +use strict; +use Fcntl qw(:DEFAULT :flock); + +use Symbol qw(gensym); +use Getopt::Std; +use IO::File; +use File::Basename; +use Cwd; + +use vars qw/$opt_a $opt_b $opt_d $opt_e $opt_h $opt_m $opt_o $opt_q/; + + +my $zonefile_suffix_default = "zone"; +my $outfile_default = "data_dns"; + +my $out_data_file = "nsdata.txt"; + +## - hashes to store the records at all, but also +## - domains, maildomains and the defined hosts +## - +my %doms = (); +my %maildoms = (); +my %hosts = () ; +my %records = () ; + + +## - filehandle +## - +my $fh = new IO::File ; + + +getopts('ab:d:e:hmo:q') || &usage(); +&usage if defined $opt_h ; + +my $i; +if (! defined $opt_q) { + print "\n command invoked: $0"; + foreach $i (@ARGV) { + print " $i"; + } + print "\n\n"; +} + +my $backup = defined($opt_b) ? $opt_b : 1; +if ( $backup != 1 && $backup != 0 ) { + print "\n wrong value for flag -b : $opt_b"; + &usage; +} + + +exit ( &main(@ARGV) ); + +sub main { + + my $infile = shift || return usage(); + + + -f $infile or die "$infile: $!"; + + my $base_infile = basename($infile); + + + my ( $line, $filename, $bind_filename); + my ( @lines, @data_file_lines, @single_file_lines); + my ( @domains, @maildomains, @hostlist, @records ); + + my ( $bind_filename, $bind_named_conf_local_master_filename, $bind_named_conf_local_slave_filename ); + my ( @bind_file_lines , @bind_named_conf_local_master_lines, @bind_named_conf_local_slave_lines); + + my ( $extension, $outdir, $outfile, $multiple_files, $add_files ); + + ## - look at the programm parameters + ## - + $extension = defined($opt_e) ? $opt_e : $zonefile_suffix_default; + $outdir = defined($opt_d) ? $opt_d : "./"; + + ## - exit if $outdir does not exist + ## - + -d $outdir or die "$outdir: $!"; + + ## - craete $outdir/bind if mot exists + ## - + -d "$outdir/bind" or mkdir("$outdir/bind", 0755); + + -d "$outdir/bind/conf" or mkdir("$outdir/bind/conf", 0755); + $bind_named_conf_local_master_filename = "$outdir/bind/conf/named.conf.local.master"; + $bind_named_conf_local_slave_filename = "$outdir/bind/conf/named.conf.local.slave"; + + + ## - like to work with the realpath + ## - + $outdir = Cwd::abs_path($outdir); + ## $outdir =~ s#^(.*)/$#$1#; + + + $outfile = defined($opt_o) ? $opt_o : $outfile_default; + $outfile = $outdir . "/" . $outfile; + $multiple_files = defined($opt_m) ? 1 : 0; + $add_files = defined($opt_a) ? 1 : 0; + + ## - Datei einlesen + ## - + if ( $fh->open($infile) ) { + flock( $fh, LOCK_SH ); + chomp (@lines = <$fh>); + flock( $fh, LOCK_UN ); + $fh->close(); + } else { + die "can't open $! for read"; + } + + + ## oder so.. + ## - + ## open( $fh ,$infile ) or die "can't open $! for read" ; + ## flock( $fh, LOCK_SH ); + ## @lines = <$fh>; + ## flock( $fh, LOCK_UN ); + ## close ( $fh ); + + ## - sichere original file + ## - + &write_file($outdir . "/" . $base_infile,@lines); + + ## - first we push into hashes, so we can sort + ## - afterwords + ## - + + foreach (@lines) { + + ## chomp ; + + ## - ignore emty lines + ## - + next if /^\s*$/o ; + + ## - ignore comments + ## - + next if /^#/o ; + + $records{$_} = 1 ; + if ( /^([\.|\&|Z])([^:]+)(.*)$/o ) { + $doms{$2} = 1 ; + } + + ## - maildomain ? + ## - + if ( /^(\@)([^:]+)(.*)/o) { + $maildoms{$2} = 1; + } + + ## - host definition ? + ## - + if ( /^(\+)([^:]+)(.*)/o) { + $hosts{$2} = 1; + } + } + + + ## - Now sort and put into the considered arrays + ## - + @domains = sort ( keys %doms ) ; + #@domains = keys %doms ; + @maildomains = sort ( keys %maildoms ) ; + @hostlist = sort ( keys %hosts ) ; + @records = sort ( sort_records keys %records); + + + + ## - schreibe domainliste, maildomainliste, hostliste, records + ## - + if ( $add_files ) { + &write_file($outdir . "/domains.lst",@domains); + &write_file($outdir . "/maildomains.lst",@maildomains); + &write_file($outdir . "/hostlist.lst",@hostlist); + &write_file($outdir . "/records.lst",@records); + } + + my $_domain =""; + my $_hostname; + my ( $_ipv6_tynidns, $_ipv6_bind, @_ipv6 ) ; + my $_ipv4 ; + my ( $_mx_host , $_mx_prio ); + my $_nameserver ; + my $_type; + #my $_filename = 0; + + my $_blank_hostname ; + my $_no_blank_hostname = 20 ; + + my $_blank_soa_comment; + my $_no_blank_soa_comment = 12; + + foreach ( @records ) { + + /(.)([^:]+).*/o ; + if ( $_domain eq get_domain($2) ) { + if ( $_type ne $1 ) { + if ( $multiple_files ) { + push ( @single_file_lines, get_record_comment($1) ); + } else { + push ( @data_file_lines, get_record_comment($1) ); + } + + push (@bind_file_lines, get_record_comment_bind($1) ); + } + if ( $multiple_files ) { + push ( @single_file_lines, $_ ); + } else { + push ( @data_file_lines, $_ ); + } + + if ( "$1" eq "&" ) { + /&([^:]+):([^:]*):([^:]+):([^:]+).*/o ; + $_blank_hostname = ""; + $_hostname = $1; + $_nameserver = $3 ; + $_hostname =~ s/\.?$_domain// ; + if ( "$_hostname" eq "" ) { + for ( my $i=0; $i < ($_no_blank_hostname - 1) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + push (@bind_file_lines, "\@${_blank_hostname}IN NS ${_nameserver}."); + } else { + if ( length($_hostname) < $_no_blank_hostname ) { + for ( my $i=0; $i < ($_no_blank_hostname - length($_hostname)) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + } else { + $_blank_hostname = " " ; + } + push (@bind_file_lines, "$_hostname${_blank_hostname}IN NS ${_nameserver}."); + } + + } elsif ( "$1" eq "\@" ) { + /\@([^:]+):([^:]*):([^:]+):([^:]+):([^:]+).*/o ; + $_blank_hostname = ""; + $_hostname = $1; + $_mx_host = $3; + $_mx_prio = $4; + $_hostname =~ s/\.?$_domain// ; + if ( "$_hostname" eq "" ) { + for ( my $i=0; $i < ($_no_blank_hostname - 1) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + push (@bind_file_lines, "\@${_blank_hostname}IN MX $_mx_prio $_mx_host."); + } else { + if ( length($_hostname) < $_no_blank_hostname ) { + for ( my $i=0; $i < ($_no_blank_hostname - length($_hostname)) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + } else { + $_blank_hostname = " " ; + } + push (@bind_file_lines, "${_hostname}${_blank_hostname}IN MX $_mx_prio $_mx_host."); + } + } elsif ( "$1" eq "+" ) { + /\+([^:]+):([^:]+):([^:]+).*/o ; + $_blank_hostname = ""; + if ( "$1" eq "$_domain" ) { + for ( my $i=0; $i < ($_no_blank_hostname - 1) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + push (@bind_file_lines, "\@${_blank_hostname}IN A $2"); + } else { + $_hostname = $1; + $_ipv4 = $2 ; + $_hostname =~ s/\.$_domain// ; + + if ( length($_hostname) < $_no_blank_hostname ) { + for ( my $i=0; $i < ($_no_blank_hostname - length($_hostname)) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + } else { + $_blank_hostname = " " ; + } + push (@bind_file_lines, "${_hostname}${_blank_hostname}IN A $_ipv4"); + } + } elsif ( "$1" eq "3" ) { + /\ ?3([^:]+):([^:]+):([^:]+).*/o ; + $_blank_hostname = ""; + $_hostname = $1 ; + $_ipv6_tynidns = $2; + $_ipv6_bind = ""; + for(my $i=0; $i<31; $i = $i +4) { + $_ipv6_bind = $_ipv6_bind . substr($_ipv6_tynidns,$i,4); + if ( $i < 28 ) { + $_ipv6_bind = $_ipv6_bind .":" ; + } + } + if ( "$1" eq "$_domain" ) { + $_ipv6_bind =~ s/:0{1,3}/:/g ; + $_ipv6_bind = reverse($_ipv6_bind); + $_ipv6_bind =~ s/:0:(0:)+/::/ ; + $_ipv6_bind = reverse($_ipv6_bind); + + for ( my $i=0; $i < ($_no_blank_hostname - 1) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + + push (@bind_file_lines, "\@${_blank_hostname}IN AAAA $_ipv6_bind"); + } else { + $_hostname =~ s/\.$_domain// ; + $_ipv6_bind =~ s/:0{1,3}/:/g ; + $_ipv6_bind = reverse($_ipv6_bind); + $_ipv6_bind =~ s/:0:(0:)+/::/ ; + $_ipv6_bind = reverse($_ipv6_bind); + + if ( length($_hostname) < $_no_blank_hostname ) { + for ( my $i=0; $i < ($_no_blank_hostname - length($_hostname)) ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + } else { + $_blank_hostname = " " ; + } + + push (@bind_file_lines, "${_hostname}${_blank_hostname}IN AAAA $_ipv6_bind"); + } + } + } else { + &write_file($filename,@single_file_lines) if ($filename); + @single_file_lines = (); + $_type = ""; + $_domain = get_domain($2); + + if ( $multiple_files ) { + $filename = $outdir . "/" . $_domain . ".file"; + push ( @single_file_lines, "## - domain: $_domain"); + push ( @single_file_lines, "## - "); + push ( @single_file_lines, get_record_comment($1) ); + push ( @single_file_lines, $_ ); + } else { + push ( @data_file_lines, "\n" ); + push ( @data_file_lines, "## - domain: $_domain"); + push ( @data_file_lines, "## - "); + push ( @data_file_lines, get_record_comment($1) ); + push ( @data_file_lines, $_ ); + } + + &write_file($bind_filename, @bind_file_lines) if ($bind_filename);; + @bind_file_lines =(); + $bind_filename = $outdir . "/bind/" . $_domain . ".zone"; + push (@bind_file_lines, "; - domain: $_domain"); + push (@bind_file_lines, "; -"); + push (@bind_file_lines, "\$TTL 43200"); + + $_blank_hostname = "" ; + for ( my $i=0; $i < $_no_blank_hostname ; $i++ ) { + $_blank_hostname = $_blank_hostname . " "; + } + + if ( "$1" eq "Z" ) { + /Z([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+):([^:]+).*/o ; + push (@bind_file_lines, "\@ $8 IN SOA $2. $3 ("); + + $_blank_soa_comment = "" ; + for ( my $i=0; $i < ($_no_blank_soa_comment - length($4)) ; $i++ ) { + $_blank_soa_comment= $_blank_soa_comment . " "; + } + push (@bind_file_lines, "${_blank_hostname}$4$_blank_soa_comment; serial"); + + $_blank_soa_comment = "" ; + for ( my $i=0; $i < ($_no_blank_soa_comment - length($5)) ; $i++ ) { + $_blank_soa_comment= $_blank_soa_comment . " "; + } + push (@bind_file_lines, "${_blank_hostname}$5$_blank_soa_comment; refresh"); + + $_blank_soa_comment = "" ; + for ( my $i=0; $i < ($_no_blank_soa_comment - length($6)) ; $i++ ) { + $_blank_soa_comment= $_blank_soa_comment . " "; + } + push (@bind_file_lines, "${_blank_hostname}$6$_blank_soa_comment; retry"); + + $_blank_soa_comment = "" ; + for ( my $i=0; $i < ($_no_blank_soa_comment - length($7)) ; $i++ ) { + $_blank_soa_comment= $_blank_soa_comment . " "; + } + push (@bind_file_lines, "${_blank_hostname}$7$_blank_soa_comment; expire"); + + $_blank_soa_comment = "" ; + for ( my $i=0; $i < ($_no_blank_soa_comment - length($8)) ; $i++ ) { + $_blank_soa_comment= $_blank_soa_comment . " "; + } + push (@bind_file_lines, "${_blank_hostname}$8$_blank_soa_comment; minimum"); + + push (@bind_file_lines, ")"); + } + + push (@bind_named_conf_local_master_lines, ""); + push (@bind_named_conf_local_master_lines, "zone \"$_domain\" {"); + push (@bind_named_conf_local_master_lines, " type master;"); + push (@bind_named_conf_local_master_lines, " file \"/etc/bind/master/$_domain.zone\";"); + push (@bind_named_conf_local_master_lines, "};"); + + + push (@bind_named_conf_local_slave_lines, ""); + push (@bind_named_conf_local_slave_lines, "zone \"$_domain\" {"); + push (@bind_named_conf_local_slave_lines, " type slave;"); + push (@bind_named_conf_local_slave_lines, " file \"/etc/bind/slave/$_domain.zone\";"); + push (@bind_named_conf_local_slave_lines, " //allow-query { any; };"); + push (@bind_named_conf_local_slave_lines, " //allow-transfer {none;};"); + push (@bind_named_conf_local_slave_lines, " masters {"); + push (@bind_named_conf_local_slave_lines, " 83.223.90.92;"); + push (@bind_named_conf_local_slave_lines, " };"); + push (@bind_named_conf_local_slave_lines, "};"); + + + } + $_type = $1; + + } + + if ( $multiple_files ) { + ## - letztes file muss noch geschrieben werdem + ## - + &write_file($filename, @single_file_lines); + } else { + ## - schreibe alles in ein file + ## - + &write_file($outfile, @data_file_lines); + } + + &write_file($bind_filename, @bind_file_lines); + + &write_file($bind_named_conf_local_master_filename, @bind_named_conf_local_master_lines); + &write_file($bind_named_conf_local_slave_filename, @bind_named_conf_local_slave_lines); + + exit 0 +} + + +sub get_domain { + + my $record = shift ; + + if ( $doms{$record} ) { + return $record ; + } else { + while ( $record =~ /([^\.]*).(.*)/o ) { + if ( $doms{$2} ) { + return $2; + } + $record = $2; + } + } + + return 1 ; + +} + + +sub get_record_comment { + my $directive_type = shift; + my $comment; + + SWITCH : { + + $1 eq "Z" and $comment = "## - SOA" , last SWITCH; + $1 eq "." and $comment = "## - SOA, NS, A" , last SWITCH; + $1 eq "&" and $comment = "## - NS, A" , last SWITCH; + $1 eq "@" and $comment = "## - MX, A" , last SWITCH; + $1 eq "=" and $comment = "## - A, PTR" , last SWITCH; + $1 eq "+" and $comment = "## - A" , last SWITCH; + $1 eq "C" and $comment = "## - CNAME" , last SWITCH; + $1 eq "^" and $comment = "## - PTR" , last SWITCH; + $1 eq "'" and $comment = "## - TEXT" , last SWITCH; + $1 eq "3" and $comment = "## - AAAA" , last SWITCH; + $1 eq "6" and $comment = "## - AAAA, PTR" , last SWITCH; + $comment = "## - unknown record"; + } + return $comment; + +} + + +sub get_record_comment_bind { + my $directive_type = shift; + my $comment; + + SWITCH : { + + $1 eq "&" and $comment = "\n;\n; NS Records\n;\n" , last SWITCH; + $1 eq "@" and $comment = "\n;\n; MX Records\n;\n" , last SWITCH; + $1 eq "+" and $comment = "\n;\n; IPv4 Hostaddresses\n;\n" , last SWITCH; + $1 eq "C" and $comment = "\n;\n; CNAME Records\n;\n" , last SWITCH; + $1 eq "3" and $comment = "\n;\n; IPv6 Hostaddresses\n;\n" , last SWITCH; + $comment = "\n;\n; unknown record\n;\n"; + } + return $comment; + +} + + +# Datei schreiben +# +sub write_file { + + my $outfile = shift ; + my @lines = @_ ; + + backup($outfile) if ( -f $outfile ); + + if (! defined $opt_q) { + print "\twrite $outfile ..\n"; + } + + $fh = new IO::File "> $outfile"; + if (defined $fh) { + foreach (@lines) { + print $fh $_ . "\n" ; + } + $fh->close(); + } + + ## - oder auch so.. + ## - + ## open ( $fh , "> $outfile") or die "can't open $! for write" ; + ## print $fh @lines ; + ## close ($fh); + +} + +# +# - backup +# +sub backup { + + my $filename = shift ; + + # Sicherungskopie erstellen + # + if ($backup) { + OUTER: for ( my $i = 0 ; $i < 10 ; $i++ ) { + for ( my $j = 0 ; $j < 10 ; $j++ ) { + my $backupfile = $filename . ".$i$j" ; + if ( -f $backupfile + || -d $backupfile + || -l $backupfile + || -p $backupfile + || -c $backupfile + || -b $backupfile + || -S $backupfile ) { + next ; + } else { + my $retval = system( "cp -f $filename $backupfile") ; + if ($retval != 0) { + die "can't store backupfile $backupfile" + } + if (! defined $opt_q) { + print "\n\tbackupfile stored in $backupfile\n"; + } + last OUTER ; + } + } + } # ende OUTER : for ( ... + } # ende if +} # end backup() + +sub sort_records { + + my ( $rval1, $rval2, $domain_a, $domain_b, $directive_a, $directive_b ); + + + $a =~ /(.)([^:]+).*/; + + ## - get directive + ## - + SWITCH : { + + $1 eq "Z" and $directive_a = 10 , last SWITCH; + $1 eq "." and $directive_a = 20 , last SWITCH; + $1 eq "&" and $directive_a = 30 , last SWITCH; + $1 eq "@" and $directive_a = 40 , last SWITCH; + $1 eq "=" and $directive_a = 50 , last SWITCH; + $1 eq "+" and $directive_a = 60 , last SWITCH; + $1 eq "C" and $directive_a = 70 , last SWITCH; + $1 eq "^" and $directive_a = 80 , last SWITCH; + $1 eq "'" and $directive_a = 90 , last SWITCH; + $1 eq "3" and $directive_a = 100, last SWITCH; + $1 eq "6" and $directive_a = 110, last SWITCH; + $directive_a = 999; + } + + ## - get domain.. + ## - + $domain_a = get_domain($2); + + $b =~ /(.)([^:]+).*/; + + ## - get directive + ## - + SWITCH : { + + $1 eq "Z" and $directive_b = 10 , last SWITCH; + $1 eq "." and $directive_b = 20 , last SWITCH; + $1 eq "&" and $directive_b = 30 , last SWITCH; + $1 eq "@" and $directive_b = 40 , last SWITCH; + $1 eq "=" and $directive_b = 50 , last SWITCH; + $1 eq "+" and $directive_b = 60 , last SWITCH; + $1 eq "C" and $directive_b = 70 , last SWITCH; + $1 eq "^" and $directive_b = 80 , last SWITCH; + $1 eq "'" and $directive_b = 90 , last SWITCH; + $1 eq "3" and $directive_b = 100, last SWITCH; + $1 eq "6" and $directive_b = 110, last SWITCH; + $directive_b = 999; + } + + ## - get domain.. + ## - + $domain_b = get_domain($2); + + $rval1 = $domain_a cmp $domain_b ; + + + if ( $rval1 == 0 ) { + $rval2 = $directive_a <=> $directive_b; + if ( $rval2 == 0 ) { + return $a cmp $b; + } else { + return $rval2; + } + } else { + return $rval1; + } + +} + + + +# +# - usage +# +sub usage { + my $file = basename($0); + $file =~ s#.*/([^/]+)$#$1# ; + + print < + +This script concatinates all zonefiles with a certain fileextension +of a given directory. + +This script takes all directives from a given djb tinydns-data-file, +sorts them and put the sortet list back into one data-file or, if +option "m" is set into one file for each domain, named by the concerning +domain. + +A copy of the (original) inputfile will be written out in . + + +Control Options: + + -a The following addition files be written: + /domains.lst.......: alphabetical list of domains + /maildomains.lst...: alphabetical list of domains + with MX entry + /hostlist.lst......: alphabetical list of all + hostentries (A - Record) + /records.lst.......: all records sorted by domain but + without any comment or emty line + + -b <0|1> a value of "1" means: befor writing a file backup existing one; + dont backup if "0". default value is "1" + + -d directory where the outfile(s) are written. defaults to + working directory + + -e write data-files with extension . defaults to + "$zonefile_suffix_default". only affected if option -m is set + + -h prints this helpcontents + + -m write one file for each domain + + -o name of outputfile. defaults to "$outfile_default". only + affect if not -m is set + + -q silent output + + +ENDE + + exit 1 ; +} diff --git a/dnscache-log b/dnscache-log new file mode 100755 index 0000000..df44afe --- /dev/null +++ b/dnscache-log @@ -0,0 +1,119 @@ +#!/usr/bin/perl -p + +# usage: tail -f /service/dnscache/log/main/current | tai64nlocal | dnscache-log +# use tail -F instead of tail -f if your tail supports it (linux, freebsd, etc) + +$| = 1; + +# strip off the year and the extra tai64 stuff. +#s/^\d{4}-(\d\d-\d\d) (\d\d:\d\d:\d\d).(\d*)/$1 $2/; + +## - changed by ckubu (strip off only tai64 stuff +s/^(\d{4}-\d\d-\d\d) (\d\d:\d\d:\d\d).(\d*)/$1 $2/; + +# convert addresses in hex to dotted decimal notation. +# ugly fix (fn 2003 01 06) +if (!m/ stats \d+ \d+ \d+ \d+/) { + s/\b([a-f0-9]{8})\b/join(".", unpack("C*", pack("H8", $1)))/eg; + ## - added by ckubu (ipv6-logfile, but only print ipv4 address)) + s/[a-f0-9]{24}([a-f0-9]{8})/join(".", unpack("C*", pack("H8", $1)))/eg; +} + +# strip out length from sent messages. +# sent slot-id length +s/sent (\d+) \d+/sent $1/; + + +### clean up some messages + +# tx gluelessness qtype thing domain where. +s/tx (\d+) (\d+) (\S+) (\S+) (.*)/"tx $1 " . queryType($2) . " $3 $4 $5"/e; + +# nodata server ttl qtype thing. +s/nodata (\S+) (\d+) (\d+) (\S+)/"nodata $1 " . queryType($2) . " $3 $4"/e; + +# cached qtype info. +s/cached (\d+)/"cached " . queryType($1)/e; + +# convert stuff like 127.0.0.2:0422:05be 1 to something more descriptive. +# query slot-id host:port qid qtype thing +s/\b([\d.]+):(\w+):(\w+) (\d+) ([-.\w]+)/printQueryLine($1, $2, $3, $4, $5)/e; + +# convert rr messages. +s/rr (\S+) (\d+) (\S+) (\S+) (\S+)/printRRLine($1, $2, $3, $4, $5)/e; + +### subs + +sub printQueryLine { + my ($host, $port, $query_id, $query_type, $query) = @_; + + # pad hostname + + my $ret = "$host:"; + $ret .= hex($port); + $ret .= ":" . hex($query_id); + $ret .= " " . queryType($query_type) . " $query"; + + return $ret; +} + +sub printRRLine { + my ($host, $ttl, $query_type, $thing, $data) = @_; + + my $ret = "rr "; + #$ret .= "$host " . padd(6, $ttl) . " "; + + ## - ckubu add: TTL= + $ret .= "$host TTL=" . padd(6, $ttl) . " "; + + $ret .= queryType($query_type) . " $thing "; + if ($query_type == 16) { # it's a txt record + # the first byte is the length. we skip it. + $data = substr($data, 2); + $ret .= "\"" . unpack("A*", pack("H*", $data)) . "\""; + } else { + $ret .= "$data"; + } + return $ret; +} + + +sub queryType { + my ($type) = shift; + + my $ret = ""; + + # i only list the ones that are in dnscache's dns.h. + SWITCH: { + ($type == 1) && do { $ret = "a"; last SWITCH; }; + ($type == 2) && do { $ret = "ns"; last SWITCH; }; + ($type == 5) && do { $ret = "cname"; last SWITCH; }; + ($type == 6) && do { $ret = "soa"; last SWITCH; }; + ($type == 12) && do { $ret = "ptr"; last SWITCH; }; + ($type == 13) && do { $ret = "hinfo"; last SWITCH; }; + ($type == 15) && do { $ret = "mx"; last SWITCH; }; + ($type == 16) && do { $ret = "txt"; last SWITCH; }; + ($type == 17) && do { $ret = "rp"; last SWITCH; }; + ($type == 24) && do { $ret = "sig"; last SWITCH; }; + ($type == 25) && do { $ret = "key"; last SWITCH; }; + ($type == 28) && do { $ret = "aaaa"; last SWITCH; }; + ($type == 252) && do { $ret = "axfr"; last SWITCH; }; + ($type == 255) && do { $ret = "any"; last SWITCH; }; + do { $ret .= "$type "; last SWITCH; }; + } + return $ret; +} + +# there has to be a better way +sub pads { + my ($amount, $item) = @_; + + return sprintf "%" . $amount . "s", $item; +} + +sub padd { + my ($amount, $item) = @_; + + return sprintf "%0" . $amount . "d", $item; +} + diff --git a/parse_djbdns_log b/parse_djbdns_log new file mode 100755 index 0000000..e9488f7 --- /dev/null +++ b/parse_djbdns_log @@ -0,0 +1,270 @@ +#!/usr/bin/python + +"""parse_djbdns_log + +Reads log files from tinydns and/or dnscache and prints them out in +human-readable form. Logs can be supplied on stdin, or listed on +the command line: + + cat @*.s | parse_djbdns_log + parse_djbdns_log @*.s + tail -f current | parse_djbdns_log + +Pipes each log file through tai64nlocal, which must be on your path. + +Requirements: + * tai64nlocal on the path + * Python 2.2 or greater + +Acknowledgments: + + * The log format descriptions by Rob Mayoff were invaluable: + http://dqd.com/~mayoff/notes/djbdns/tinydns-log.html + http://dqd.com/~mayoff/notes/djbdns/dnscache-log.html + + * Faried Nawaz's dnscache log parser was the original inspiration: + http://www.hungry.com/~fn/dnscache-log.pl.txt + +Written by Greg Ward 2001/12/13. + +Modified to handle IPv6 addresses (as logged by djbdns with the patch at +http://www.fefe.de/dns/), 2003/05/03-04, prodded and tested by Jakob +Hirsch . + +Modified to handle dnscache's AXFR request log lines by Malte Tancred +(http://tancred.com/malte.html), 2005/12/20. +""" + +__revision__ = "$Id: parse_djbdns_log,v 1.4 2005/12/20 13:39:36 greg Exp $" + +import sys, re +from popen2 import popen2 +from time import strftime, gmtime +from struct import pack + +# common components of line-matching regexes +timestamp_pat = r'[\d-]+ [\d:\.]+' # output of tai64nlocal +hex4_pat = r'[0-9a-f]{4}' +ip_pat = r'[0-9a-f]{8,32}' # IPv4 or IPv6 addresses in hex + +# discriminate between dnscache and tinydns log lines +tinydns_log_re = re.compile( + r'(%s) (%s):(%s):(%s) ([\+\-IC/]) (%s) (.*)' + % (timestamp_pat, ip_pat, hex4_pat, hex4_pat, hex4_pat)) +dnscache_log_re = re.compile(r'(%s) (\w+)(.*)' % timestamp_pat) + +query_type = { + 1: "a", + 2: "ns", + 5: "cname", + 6: "soa", + 12: "ptr", + 13: "hinfo", + 15: "mx", + 16: "txt", + 17: "rp", + 24: "sig", + 25: "key", + 28: "aaaa", + 38: "a6", + 252: "axfr", + 255: "any", +} + +# for tinydns only +query_drop_reason = { + "-": "no authority", + "I": "invalid query", + "C": "invalid class", + } + + +def warn (filename, msg): + sys.stderr.write("warning: %s: %s\n" % (filename, msg)) + +def convert_ip (ip): + """Convert a hex string representing an IP address to conventional + human-readable form, ie. dotted-quad decimal for IPv4, and + 8 colon-separated hex shorts for IPv6. + """ + if len(ip) == 8: + # IPv4, eg. "7f000001" -> "127.0.0.1" + return "%d.%d.%d.%d" % tuple(map(ord, pack(">L", long(ip, 16)))) + elif len(ip) == 32: + # IPv6 is actually simpler -- it's just a string-slicing operation, + # eg. "00000000000000000000ffff7f000001" -> + # "0000:0000:0000:0000:0000:ffff:7f00:0001" + return ":".join([ip[(4*i) : (4*i+4)] for i in range(8)]) + + +def _cvt_ip (match): + return convert_ip(match.group(1)) + +def _cvt_port (match): + return ":" + str(int(match.group(1), 16)) + +def decode_client (words, i): + chunks = words[i].split(":") + if len(chunks) == 2: # ip:port + words[i] = "%s:%d" % (convert_ip(chunks[0]), int(chunks[1], 16)) + elif len(chunks) == 3: + words[i] = "%s:%d (id %d)" % (convert_ip(chunks[0]), + int(chunks[1], 16), + int(chunks[2], 16)) + +def decode_ip (words, i): + words[i] = convert_ip(words[i]) + +def decode_ttl (words, i): + words[i] = "TTL=%s" % words[i] + +def decode_serial (words, i): + serial = int(words[i]) + words[i] = "#%d" % serial + +def decode_type (words, i): + qt = words[i] + words[i] = query_type.get(int(qt), qt) + +def handle_dnscache_log (line, match): + (timestamp, event, data) = match.groups() + + words = data.split() + if event == "cached": + if words[0] not in ("cname", "ns", "nxdomain"): + decode_type(words, 0) + + elif event == "drop": + decode_serial(words, 0) + + elif event == "lame": + decode_ip(words, 0) + + elif event == "nodata": + decode_ip(words, 0) + decode_ttl(words, 1) + decode_type(words, 2) + + elif event == "nxdomain": + decode_ip(words, 0) + decode_ttl(words, 1) + + elif event == "query": + decode_serial(words, 0) + decode_client(words, 1) + decode_type(words, 2) + + elif event == "rr": + decode_ip(words, 0) + decode_ttl(words, 1) + if words[2] not in ("cname", "mx", "ns", "ptr", "soa"): + decode_type(words, 2) + if words[2] == "a": # decode answer to an A query + decode_ip(words, 4) + if words[2] == "txt": # text record + response = words[4] + if response.endswith("..."): + ellipsis = "..." + response = response[0:-3] + else: + ellipsis = "" + length = int(response[0:2], 16) + chars = [] + for i in range(1, len(response)/2): + chars.append(chr(int(response[2*i : (2*i)+2], 16))) + words[4] = "%d:\"%s%s\"" % (length, "".join(chars), ellipsis) + + elif event == "sent": + decode_serial(words, 0) + + elif event == "stats": + words[0] = "count=%s" % words[0] + words[1] = "motion=%s" % words[1] + words[2] = "udp-active=%s" % words[2] + words[3] = "tcp-active=%s" % words[3] + + elif event == "tx": + words[0] = "g=%s" % words[0] + decode_type(words, 1) + # words[2] = name + # words[3] = control (domain for which these servers are believed + # to be authoritative) + for i in range(4, len(words)): + decode_ip(words, i) + + elif event in ("tcpopen", "tcpclose"): + decode_client(words, 0) + + print timestamp, event, " ".join(words) + + +def handle_tinydns_log (line, match): + (timestamp, ip, port, id, code, type, name) = match.groups() + ip = convert_ip(ip) + port = int(port, 16) + id = int(id, 16) + type = int(type, 16) # "001c" -> 28 + type = query_type.get(type, type) # 28 -> "aaaa" + + print timestamp, + + if code == "+": + print ("sent response to %s:%s (id %s): %s %s" + % (ip, port, id, type, name)) + elif code in ("-", "I", "C"): + reason = query_drop_reason[code] + print ("dropped query (%s) from %s:%s (id %s): %s %s" + % (reason, ip, port, id, type, name)) + elif code == "/": + print ("dropped query (couldn't parse) from %s:%s" + % (ip, port)) + else: + print ("%s from %s:%s (id %s): %s %s" + % (code, ip, port, id, type, name)) + + +def parse_logfile (file, filename): + # Open pipe to tai64nlocal: we will write lines of our input (the + # raw log file) to it, and read log lines with readable timestamps + # from it. + (tai_stdout, tai_stdin) = popen2("tai64nlocal", 0) + + for line in file: + tai_stdin.write(line) + line = tai_stdout.readline() + + match = tinydns_log_re.match(line) + if match: + handle_tinydns_log(line, match) + continue + + match = dnscache_log_re.match(line) + if match: + handle_dnscache_log(line, match) + continue + + sys.stdout.write(line) + +# parse_logfile () + + +def main (): + + if len(sys.argv) > 1: + for filename in sys.argv[1:]: + if filename == "-": + parse_logfile(sys.stdin, "(stdin)") + else: + file = open(filename) + parse_logfile(file, filename) + file.close() + else: + parse_logfile(sys.stdin, "(stdin)") + + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + sys.exit("interrupted") diff --git a/tail_djb_dnscache.sh b/tail_djb_dnscache.sh new file mode 100755 index 0000000..c868f2d --- /dev/null +++ b/tail_djb_dnscache.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +multitail -e /service/dnscache/log/main/current | tai64nlocal | /root/scripts/dnscache-log diff --git a/tail_djbtinydns.sh b/tail_djbtinydns.sh new file mode 100755 index 0000000..0133a5c --- /dev/null +++ b/tail_djbtinydns.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +multitail -e /service/tinydns/log/main/current | tai64nlocal | /root/scripts/tinydns-log_ckubu.pl diff --git a/tail_djbtinydns6.sh b/tail_djbtinydns6.sh new file mode 100755 index 0000000..762c93f --- /dev/null +++ b/tail_djbtinydns6.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +multitail -e /service/tinydns6/log/main/current | tai64nlocal | /root/scripts/tinydns6-log_ckubu.pl diff --git a/tail_qmail-send.sh b/tail_qmail-send.sh new file mode 100755 index 0000000..9a2600e --- /dev/null +++ b/tail_qmail-send.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +#multitail -e /var/log/qmail/send/current | tai64n2tai | gawk '{$1=substr(strftime("%c",$1),0,23);print}' +multitail -e /var/log/qmail/send/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' +#multitail /var/log/qmail/send/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' +#tail -f /var/log/qmail/send/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' + +exit 0 diff --git a/tail_qmail-smtpd.sh b/tail_qmail-smtpd.sh new file mode 100755 index 0000000..269e6e3 --- /dev/null +++ b/tail_qmail-smtpd.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +#multitail -e /var/log/qmail/smtpd/current | tai64n2tai | gawk '{$1=substr(strftime("%c",$1),0,23);print}' +multitail -e /var/log/qmail/smtpd/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' +#multitail /var/log/qmail/smtpd/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' +#tail -f /var/log/qmail/smtpd/current | tai64nlocal | gawk '{$2=substr($2,1,8);print}' + +exit 0 diff --git a/tinydns-log_ckubu.pl b/tinydns-log_ckubu.pl new file mode 100755 index 0000000..1b1dc31 --- /dev/null +++ b/tinydns-log_ckubu.pl @@ -0,0 +1,139 @@ +#!/usr/bin/perl -p + +use Sys::Hostname; +$myhost = hostname; +#$myhost =~ s/^([^.]+).*/$1/ ; + +# tinydns log formatting utility +# based on Faried Nawaz's logfile formatter for dnscache +# by Kenji Rikitake 29-JUL-2000 +# please put this on dnscache.com ftp site. + +# convert addresses in hex to dotted decimal notation. +## - wthout ipv6 patch +## - +#s/\b([a-f0-9]{8})\b/join(".", unpack("C*", pack("H8", $1)))/eg; + +## - within ipv6 +## - +s/[a-f0-9]{24}([a-f0-9]{8})/join(".", unpack("C*", pack("H8", $1)))/eg; + +### clean up some messages +# convert stuff like 127.0.0.2:0422:05be to something more descriptive. +# query tai64n host:port:qid flag qtype thing +# keep tai64n header as is - use tai64nlocal to convert it to TAI + + +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-\I\/]) \b([a-f0-9]+) \b([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-CIX\/]?)\s?\b([a-f0-9]+) \b([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; + + +## - if original logfile will be parsed +## - +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-CIX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; + +## - if logfile is tai65nlocal konverted +## - +#s/^([^\.]+).([0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-\ICX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/$1." ".printQueryLine($3,$4,$5,$6,$7,$8)/e; + +## - additional print (short) hostname +## - +s/^([^\.]+).([0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-\ICX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/"[$myhost] ".$1." ".printQueryLine($3,$4,$5,$6,$7,$8)/e; + + + +### subs + +sub printQueryLine { + my ($host, $port, $query_id, $flag, $query_type, $query) = @_; + + # pad hostname + + #my $ret = "$host:"; + #$ret .= hex($port); + #$ret .= ":" . hex($query_id); + #$ret .= " " . $flag; + my $ret = queryHandle($host, hex($port), hex($query_id), $flag); + $ret .= " " . queryType(hex($query_type)) . " $query"; + + return $ret; +} + +## -sub queryType { +## - my ($type) = shift; +## - +## - my $ret = ""; +## - +## - # i only list the ones that are in dnscache's dns.h. +## - SWITCH: { +## - ($type == 1) && do { $ret = "A"; last SWITCH; }; +## - ($type == 2) && do { $ret = "NS"; last SWITCH; }; +## - ($type == 5) && do { $ret = "CNAME"; last SWITCH; }; +## - ($type == 6) && do { $ret = "SOA"; last SWITCH; }; +## - ($type == 11) && do { $ret = "WKS"; last SWITCH; }; +## - ($type == 12) && do { $ret = "PTR"; last SWITCH; }; +## - ($type == 13) && do { $ret = "HINFO"; last SWITCH; }; +## - ($type == 14) && do { $ret = "MINFo"; last SWITCH; }; +## - ($type == 15) && do { $ret = "MX"; last SWITCH; }; +## - ($type == 16) && do { $ret = "TXT"; last SWITCH; }; +## - ($type == 17) && do { $ret = "RP"; last SWITCH; }; +## - ($type == 18) && do { $ret = "AFSDB"; last SWITCH; }; +## - ($type == 20) && do { $ret = "ISDN"; last SWITCH; }; +## - ($type == 21) && do { $ret = "RT"; last SWITCH; }; +## - ($type == 22) && do { $ret = "NSAP"; last SWITCH; }; +## - ($type == 23) && do { $ret = "NSAP-PTR"; last SWITCH; }; +## - ($type == 24) && do { $ret = "SIG"; last SWITCH; }; +## - ($type == 25) && do { $ret = "KEY"; last SWITCH; }; +## - ($type == 26) && do { $ret = "PX"; last SWITCH; }; +## - ($type == 28) && do { $ret = "AAAA"; last SWITCH; }; +## - ($type == 29) && do { $ret = "LOC"; last SWITCH; }; +## - ($type == 30) && do { $ret = "NXT"; last SWITCH; }; +## - ($type == 33) && do { $ret = "SRV"; last SWITCH; }; +## - ($type == 35) && do { $ret = "NAPTR"; last SWITCH; }; +## - ($type == 36) && do { $ret = "KX"; last SWITCH; }; +## - ($type == 37) && do { $ret = "CERT"; last SWITCH; }; +## - ($type == 38) && do { $ret = "A6"; last SWITCH; }; +## - ($type == 42) && do { $ret = "APL"; last SWITCH; }; +## - ($type == 249) && do { $ret = "TKEY"; last SWITCH; }; +## - ($type == 250) && do { $ret = "TSIG"; last SWITCH; }; +## - ($type == 251) && do { $ret = "IXFR"; last SWITCH; }; +## - ($type == 252) && do { $ret = "AXFR"; last SWITCH; }; +## - ($type == 255) && do { $ret = "ANY"; last SWITCH; }; +## - do { $ret .= "$type "; last SWITCH; }; +## - } +## - return $ret; +## -} + +# DNS query type codes from the following RFCs: +# 1035,1183,1348,1876,1995,2065,2163,2230,2535,2538,2845,2874,2915,2930,3123 +%QTYPE = ( + 1, "A", 2, "NS", 5, "CNAME", 6, "SOA", 11, "WKS", 12, "PTR", + 13, "HINFO", 14, "MINFO", 15, "MX", 16, "TXT", 17, "RP", + 18, "AFSDB", 20, "ISDN", 21, "RT", 22, "NSAP", 23, "NSAP-PTR", + 24, "SIG", 25, "KEY", 26, "PX", 28, "AAAA", 29, "LOC", 30, "NXT", + 33, "SRV", 35, "NAPTR", 36, "KX", 37, "CERT", 38, "A6", 42, "APL", + 249, "TKEY", 250, "TSIG", 251, "IXFR", 252, "AXFR", 255, "ANY" +); + +sub queryType { + my ($type) = shift; + return $QTYPE{$type} || $type; +} + +sub queryHandle { + my ($q_host, $q_port, $q_id, $q_flag) = @_; + + my $ret = ""; + + # i only list the ones that are in dnscache's dns.h. + SWITCH: { + ($q_flag =~ m/\+/) && do { $ret = "sent response to $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m/-/) && do { $ret = "dropped query (no authority) from $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#/#) && do { $ret = "dropped query (couldn't parse) from $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#I#) && do { $ret = "[WARN] sent RCODE of 4 (NOTIMP) to $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#C#) && do { $ret = "[WARN] sent RCODE of 1 (FORMERR) to $q_host:$q_port (id $q_id): "; last SWITCH; }; + do { $ret .= "[??] $q_host:$q_port (id $q_id): $q_flag "; last SWITCH; }; + } + return $ret; +} + diff --git a/tinydns6-log_ckubu.pl b/tinydns6-log_ckubu.pl new file mode 100755 index 0000000..b8c140d --- /dev/null +++ b/tinydns6-log_ckubu.pl @@ -0,0 +1,144 @@ +#!/usr/bin/perl -p + +use Sys::Hostname; +$myhost = hostname; +#$myhost =~ s/^([^.]+).*/$1/ ; + +# tinydns log formatting utility +# based on Faried Nawaz's logfile formatter for dnscache +# by Kenji Rikitake 29-JUL-2000 +# please put this on dnscache.com ftp site. + +# convert addresses in hex to dotted decimal notation. +## - wthout ipv6 patch +## - +#s/\b([a-f0-9]{8})\b/join(".", unpack("C*", pack("H8", $1)))/eg; + +## - within ipv6 +## - +#s/[a-f0-9]{24}([a-f0-9]{8})/join(".", unpack("C*", pack("H8", $1)))/eg; + + +### clean up some messages +# convert stuff like 127.0.0.2:0422:05be to something more descriptive. +# query tai64n host:port:qid flag qtype thing +# keep tai64n header as is - use tai64nlocal to convert it to TAI + + +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-\I\/]) \b([a-f0-9]+) \b([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-CIX\/]?)\s?\b([a-f0-9]+) \b([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; + + +## - if original logfile will be parsed +## - +#s/^(@[a-f0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-CIX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/$1." ".printQueryLine($2,$3,$4,$5,$6,$7)/e; + +## - if logfile is tai65nlocal konverted +## - +#s/^([^\.]+).([0-9]+) \b([\d.]+):(\w+):(\w+) ([\+\-\ICX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/$1." ".printQueryLine($3,$4,$5,$6,$7,$8)/e; + +## - additional print (short) hostname +## - +s/^([^\.]+).([0-9]+) \b([\w.]+):(\w+):(\w+) ([\+\-\ICX\/]?)\s?\b([a-f0-9]+) ([-.\w]+)/"[$myhost] ".$1." ".printQueryLine($3,$4,$5,$6,$7,$8)/e; + +## - ipv6 embedded ipv4-addresses +## - +#s/00000000000000000000ffff//; +s/([a-f0-9]{4})([a-f0-9]{4})/$1:$2:/g; + + +### subs + +sub printQueryLine { + my ($host, $port, $query_id, $flag, $query_type, $query) = @_; + + # pad hostname + + #my $ret = "$host:"; + #$ret .= hex($port); + #$ret .= ":" . hex($query_id); + #$ret .= " " . $flag; + my $ret = queryHandle($host, hex($port), hex($query_id), $flag); + $ret .= " " . queryType(hex($query_type)) . " $query"; + + return $ret; +} + +## -sub queryType { +## - my ($type) = shift; +## - +## - my $ret = ""; +## - +## - # i only list the ones that are in dnscache's dns.h. +## - SWITCH: { +## - ($type == 1) && do { $ret = "A"; last SWITCH; }; +## - ($type == 2) && do { $ret = "NS"; last SWITCH; }; +## - ($type == 5) && do { $ret = "CNAME"; last SWITCH; }; +## - ($type == 6) && do { $ret = "SOA"; last SWITCH; }; +## - ($type == 11) && do { $ret = "WKS"; last SWITCH; }; +## - ($type == 12) && do { $ret = "PTR"; last SWITCH; }; +## - ($type == 13) && do { $ret = "HINFO"; last SWITCH; }; +## - ($type == 14) && do { $ret = "MINFo"; last SWITCH; }; +## - ($type == 15) && do { $ret = "MX"; last SWITCH; }; +## - ($type == 16) && do { $ret = "TXT"; last SWITCH; }; +## - ($type == 17) && do { $ret = "RP"; last SWITCH; }; +## - ($type == 18) && do { $ret = "AFSDB"; last SWITCH; }; +## - ($type == 20) && do { $ret = "ISDN"; last SWITCH; }; +## - ($type == 21) && do { $ret = "RT"; last SWITCH; }; +## - ($type == 22) && do { $ret = "NSAP"; last SWITCH; }; +## - ($type == 23) && do { $ret = "NSAP-PTR"; last SWITCH; }; +## - ($type == 24) && do { $ret = "SIG"; last SWITCH; }; +## - ($type == 25) && do { $ret = "KEY"; last SWITCH; }; +## - ($type == 26) && do { $ret = "PX"; last SWITCH; }; +## - ($type == 28) && do { $ret = "AAAA"; last SWITCH; }; +## - ($type == 29) && do { $ret = "LOC"; last SWITCH; }; +## - ($type == 30) && do { $ret = "NXT"; last SWITCH; }; +## - ($type == 33) && do { $ret = "SRV"; last SWITCH; }; +## - ($type == 35) && do { $ret = "NAPTR"; last SWITCH; }; +## - ($type == 36) && do { $ret = "KX"; last SWITCH; }; +## - ($type == 37) && do { $ret = "CERT"; last SWITCH; }; +## - ($type == 38) && do { $ret = "A6"; last SWITCH; }; +## - ($type == 42) && do { $ret = "APL"; last SWITCH; }; +## - ($type == 249) && do { $ret = "TKEY"; last SWITCH; }; +## - ($type == 250) && do { $ret = "TSIG"; last SWITCH; }; +## - ($type == 251) && do { $ret = "IXFR"; last SWITCH; }; +## - ($type == 252) && do { $ret = "AXFR"; last SWITCH; }; +## - ($type == 255) && do { $ret = "ANY"; last SWITCH; }; +## - do { $ret .= "$type "; last SWITCH; }; +## - } +## - return $ret; +## -} + +# DNS query type codes from the following RFCs: +# 1035,1183,1348,1876,1995,2065,2163,2230,2535,2538,2845,2874,2915,2930,3123 +%QTYPE = ( + 1, "A", 2, "NS", 5, "CNAME", 6, "SOA", 11, "WKS", 12, "PTR", + 13, "HINFO", 14, "MINFO", 15, "MX", 16, "TXT", 17, "RP", + 18, "AFSDB", 20, "ISDN", 21, "RT", 22, "NSAP", 23, "NSAP-PTR", + 24, "SIG", 25, "KEY", 26, "PX", 28, "AAAA", 29, "LOC", 30, "NXT", + 33, "SRV", 35, "NAPTR", 36, "KX", 37, "CERT", 38, "A6", 42, "APL", + 249, "TKEY", 250, "TSIG", 251, "IXFR", 252, "AXFR", 255, "ANY" +); + +sub queryType { + my ($type) = shift; + return $QTYPE{$type} || $type; +} + +sub queryHandle { + my ($q_host, $q_port, $q_id, $q_flag) = @_; + + my $ret = ""; + + # i only list the ones that are in dnscache's dns.h. + SWITCH: { + ($q_flag =~ m/\+/) && do { $ret = "sent response to $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m/-/) && do { $ret = "dropped query (no authority) from $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#/#) && do { $ret = "dropped query (couldn't parse) from $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#I#) && do { $ret = "[WARN] sent RCODE of 4 (NOTIMP) to $q_host:$q_port (id $q_id): "; last SWITCH; }; + ($q_flag =~ m#C#) && do { $ret = "[WARN] sent RCODE of 1 (FORMERR) to $q_host:$q_port (id $q_id): "; last SWITCH; }; + do { $ret .= "[??] $q_host:$q_port (id $q_id): $q_flag "; last SWITCH; }; + } + return $ret; +} + diff --git a/update6_djbdns_roots.sh b/update6_djbdns_roots.sh new file mode 100755 index 0000000..e9cad8c --- /dev/null +++ b/update6_djbdns_roots.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +ipv6=false +[ -n "`which dnsip6`" ] && ipv6=true + +if [ -f /etc/dnsroots.global ] ; then + if [ ! -f /etc/dnsroots.global.ORIG ] ; then + cp /etc/dnsroots.global /etc/dnsroots.global.ORIG + fi +fi + +root_servers=`dnsqr ns . | awk '/answer:/ { print $5; }' | sort` + +> /etc/dnsroots.global + +for server in $root_servers ; do + echo "`dnsip $server`" >> /etc/dnsroots.global + if $ipv6 ; then + ip6=`dnsqr aaaa $server | awk '/answer:/ { print $5; }'` + if [ -n "$ip6" ] ; then + echo "$ip6" >> /etc/dnsroots.global + fi + fi +done + +cp /etc/dnsroots.global /service/dnscache/root/servers/@ +cp /etc/dnsroots.global /service/dnscache6/root/servers/@ +svc -du /service/dnscache +svc -du /service/dnscache6 diff --git a/update_djbdns_roots.sh b/update_djbdns_roots.sh new file mode 100755 index 0000000..fbefda7 --- /dev/null +++ b/update_djbdns_roots.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin + +if [ -f /etc/dnsroots.global ] ; then + if [ ! -f /etc/dnsroots.global.ORIG ] ; then + cp /etc/dnsroots.global /etc/dnsroots.global.ORIG + fi +fi + +dnsip `dnsqr ns . | awk '/answer:/ { print $5; }' |sort` > /etc/dnsroots.global +cp /etc/dnsroots.global /service/dnscache/root/servers/@ +svc -du /service/dnscache + diff --git a/update_ipv4_adress_space.sh b/update_ipv4_adress_space.sh new file mode 100755 index 0000000..1bfc39b --- /dev/null +++ b/update_ipv4_adress_space.sh @@ -0,0 +1,59 @@ +#!/bin/sh + +update_url="http://www.iana.org/assignments/ipv4-address-space/ipv4-address-space.txt" + +base_dnscache_dir=/opt/dnscache +dnscache_ip_dir=${base_dnscache_dir}/root/ip + +if [ ! -d $base_dnscache_dir -o ! -d $dnscache_ip_dir ]; then + echo + echo "[ ERROR ]: Installtion directory for dnscache not found" + echo " exiting now.." + echo + exit 1 +fi + + + + +tmp_file="/tmp/ipv4_addresss_space.$$.lst" + +wget $update_url -O $tmp_file > /dev/null 2>&1 + +if [ $? -gt 0 ];then + echo + echo "[ ERROR ]: cannot fetch $update_url " + echo " exiting now.." + echo + rm -f $tmp_file + exit 2 +fi + +adress_spaces=`grep -e " \(ALLOCATED\)$\|\(LEGACY\)$" $tmp_file | awk '{print$1}' | cut -d "/" -f 1 | sed -e's/^0*\(.*\)$/\1/'` + +if [ -z "$adress_spaces" ] ; then + echo + echo "[ ERROR ]: No adress space data found $update_url " + echo " exiting now.." + echo + rm -f $tmp_file + exit 3 +fi + +## - delete old entries.. +## - +rm -rf $dnscache_ip_dir/* + +cd $dnscache_ip_dir + +for i in $adress_spaces; do + touch ${i} +done + +## - send the servive a HUP signal +## - +svc -h $base_dnscache_dir + +rm -f $tmp_file + +exit 0