Changeset 636
- Timestamp:
- 05/15/14 16:21:25 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/DNSDB.pm
r635 r636 5847 5847 } 5848 5848 5849 ## And now the meat. 5850 5849 5851 ##fixme? append . to all host/val hostnames 5850 if ($typemap{$type} eq 'SOA') { 5851 5852 5853 5852 5853 if ($typemap{$type} eq 'SOA') { 5854 # host contains pri-ns:responsible 5855 # val is abused to contain refresh:retry:expire:minttl 5854 5856 ##fixme: "manual" serial vs tinydns-autoserial 5855 5856 5857 5858 5857 # let's be explicit about abusing $host and $val 5858 my ($email, $primary) = (split /:/, $host)[0,1]; 5859 my ($refresh, $retry, $expire, $min_ttl) = (split /:/, $val)[0,1,2,3]; 5860 if ($revrec eq 'y') { 5859 5861 ##fixme: have to publish SOA records for each v4 /24 in sub-/16, and each /16 in sub-/8 5860 5862 # what about v6? 5861 5863 # -> only need SOA for local chunks offset from reverse delegation boundaries, so v6 is fine 5862 $zone = NetAddr::IP->new($zone); 5863 # handle split-n-multiply SOA for off-octet (8 < mask < 16) or (16 < mask < 24) v4 zones 5864 if (!$zone->{isv6} && ($zone->masklen < 24) && ($zone->masklen % 8 != 0)) { 5865 foreach my $szone ($zone->split($zone->masklen + (8 - $zone->masklen % 8))) { 5866 $szone = _ZONE($szone, 'ZONE.in-addr.arpa', 'r', '.'); 5867 print $datafile "Z$szone:$primary:$email"."::$refresh:$retry:$expire:$min_ttl:$ttl:$stamp:$loc\n" 5868 or die $!; 5869 } 5870 return; # skips "default" bits just below 5871 } 5872 $zone = _ZONE($zone, 'ZONE', 'r', '.').($zone->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 5873 } 5874 print $datafile "Z$zone:$primary:$email"."::$refresh:$retry:$expire:$min_ttl:$ttl:$stamp:$loc\n" 5875 or die $!; 5876 5877 } elsif ($typemap{$type} eq 'A') { 5878 5879 print $datafile "+$host:$val:$ttl:$stamp:$loc\n" or die $!; 5880 5881 } elsif ($typemap{$type} eq 'NS') { 5882 5883 if ($revrec eq 'y') { 5884 $val = NetAddr::IP->new($val); 5885 # handle split-n-multiply SOA for off-octet (8 < mask < 16) or (16 < mask < 24) v4 zones 5886 if (!$val->{isv6} && ($val->masklen < 24) && ($val->masklen % 8 != 0)) { 5887 foreach my $szone ($val->split($val->masklen + (8 - $val->masklen % 8))) { 5888 my $szone2 = _ZONE($szone, 'ZONE.in-addr.arpa', 'r', '.'); 5889 next if $$recflags{$szone2} && $$recflags{$szone2} > $val->masklen; 5890 print $datafile "\&$szone2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5891 $$recflags{$szone2} = $val->masklen; 5892 } 5893 } elsif ($val->{isv6} && ($val->masklen < 64) && ($val->masklen % 4 !=0)) { 5894 foreach my $szone ($val->split($val->masklen + (4 - $val->masklen % 4))) { 5895 my $szone2 = _ZONE($szone, 'ZONE.ip6.arpa', 'r', '.'); 5896 next if $$recflags{$szone2} && $$recflags{$szone2} > $val->masklen; 5897 print $datafile "\&$szone2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5898 $$recflags{$szone2} = $val->masklen; 5899 } 5900 } else { 5901 my $val2 = _ZONE($val, 'ZONE', 'r', '.').($val->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 5902 print $datafile "\&$val2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5903 $$recflags{$val2} = $val->masklen; 5904 } 5905 } else { 5906 print $datafile "\&$host"."::$val:$ttl:$stamp:$loc\n" or die $!; 5907 } 5908 5909 } elsif ($typemap{$type} eq 'AAAA') { 5910 5911 # print $datafile ":$host:28:"; 5912 my $altgrp = 0; 5913 my @altconv; 5914 # Split in to up to 8 groups of hex digits (allows for IPv6 :: 0-collapsing) 5915 foreach (split /:/, $val) { 5916 if (/^$/) { 5917 # flag blank entry; this is a series of 0's of (currently) unknown length 5918 $altconv[$altgrp++] = 's'; 5919 } else { 5920 # call sub to convert 1-4 hex digits to 2 string-rep octal bytes 5921 $altconv[$altgrp++] = octalize($_) 5922 } 5923 } 5924 my $prefix = ":$host:28:"; 5925 foreach my $octet (@altconv) { 5926 # if not 's', output 5927 $prefix .= $octet unless $octet =~ /^s$/; 5928 # if 's', output (9-array length)x literal '\000\000' 5929 $prefix .= '\000\000'x(9-$altgrp) if $octet =~ /^s$/; 5930 } 5931 print $datafile "$prefix:$ttl:$stamp:$loc\n" or die $!; 5932 5933 } elsif ($typemap{$type} eq 'MX') { 5864 # anyone who says they need sub-nibble v6 delegations, at this time, needs their head examined. 5865 $zone = NetAddr::IP->new($zone); 5866 # handle split-n-multiply SOA for off-octet (8 < mask < 16) or (16 < mask < 24) v4 zones 5867 if (!$zone->{isv6} && ($zone->masklen < 24) && ($zone->masklen % 8 != 0)) { 5868 foreach my $szone ($zone->split($zone->masklen + (8 - $zone->masklen % 8))) { 5869 $szone = _ZONE($szone, 'ZONE.in-addr.arpa', 'r', '.'); 5870 print $datafile "Z$szone:$primary:$email"."::$refresh:$retry:$expire:$min_ttl:$ttl:$stamp:$loc\n" 5871 or die $!; 5872 } 5873 return; # skips "default" bits just below 5874 } 5875 $zone = _ZONE($zone, 'ZONE', 'r', '.').($zone->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 5876 } 5877 print $datafile "Z$zone:$primary:$email"."::$refresh:$retry:$expire:$min_ttl:$ttl:$stamp:$loc\n" 5878 or die $!; 5879 5880 } elsif ($typemap{$type} eq 'A') { 5881 5882 print $datafile "+$host:$val:$ttl:$stamp:$loc\n" or die $!; 5883 5884 } elsif ($typemap{$type} eq 'NS') { 5885 5886 if ($revrec eq 'y') { 5887 $val = NetAddr::IP->new($val); 5888 # handle split-n-multiply SOA for off-octet (8 < mask < 16) or (16 < mask < 24) v4 zones 5889 if (!$val->{isv6} && ($val->masklen < 24) && ($val->masklen % 8 != 0)) { 5890 foreach my $szone ($val->split($val->masklen + (8 - $val->masklen % 8))) { 5891 my $szone2 = _ZONE($szone, 'ZONE.in-addr.arpa', 'r', '.'); 5892 next if $$recflags{$szone2} && $$recflags{$szone2} > $val->masklen; 5893 print $datafile "\&$szone2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5894 $$recflags{$szone2} = $val->masklen; 5895 } 5896 } elsif ($val->{isv6} && ($val->masklen < 64) && ($val->masklen % 4 !=0)) { 5897 foreach my $szone ($val->split($val->masklen + (4 - $val->masklen % 4))) { 5898 my $szone2 = _ZONE($szone, 'ZONE.ip6.arpa', 'r', '.'); 5899 next if $$recflags{$szone2} && $$recflags{$szone2} > $val->masklen; 5900 print $datafile "\&$szone2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5901 $$recflags{$szone2} = $val->masklen; 5902 } 5903 } else { 5904 my $val2 = _ZONE($val, 'ZONE', 'r', '.').($val->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'); 5905 print $datafile "\&$val2"."::$host:$ttl:$stamp:$loc\n" or die $!; 5906 $$recflags{$val2} = $val->masklen; 5907 } 5908 } else { 5909 print $datafile "\&$host"."::$val:$ttl:$stamp:$loc\n" or die $!; 5910 } 5911 5912 } elsif ($typemap{$type} eq 'AAAA') { 5913 5914 # print $datafile ":$host:28:"; 5915 my $altgrp = 0; 5916 my @altconv; 5917 # Split in to up to 8 groups of hex digits (allows for IPv6 :: 0-collapsing) 5918 foreach (split /:/, $val) { 5919 if (/^$/) { 5920 # flag blank entry; this is a series of 0's of (currently) unknown length 5921 $altconv[$altgrp++] = 's'; 5922 } else { 5923 # call sub to convert 1-4 hex digits to 2 string-rep octal bytes 5924 $altconv[$altgrp++] = octalize($_) 5925 } 5926 } 5927 my $prefix = ":$host:28:"; 5928 foreach my $octet (@altconv) { 5929 # if not 's', output 5930 $prefix .= $octet unless $octet =~ /^s$/; 5931 # if 's', output (9-array length)x literal '\000\000' 5932 $prefix .= '\000\000'x(9-$altgrp) if $octet =~ /^s$/; 5933 } 5934 print $datafile "$prefix:$ttl:$stamp:$loc\n" or die $!; 5935 5936 } elsif ($typemap{$type} eq 'MX') { 5934 5937 5935 5938 ##fixme: what if we get an MX AXFRed into a reverse zone? 5936 5937 5938 5939 print $datafile "\@$host"."::$val:$dist:$ttl:$stamp:$loc\n" or die $!; 5940 5941 } elsif ($typemap{$type} eq 'TXT') { 5939 5942 5940 5943 ##fixme: split v-e-r-y long TXT strings? will need to do so for BIND export, at least 5941 5942 5943 5944 5945 5946 5947 5948 5949 5944 if ($revrec eq 'n') { 5945 $val =~ s/:/\\072/g; # may need to replace other symbols 5946 print $datafile "'$host:$val:$ttl:$stamp:$loc\n" or die $!; 5947 } else { 5948 $host =~ s/:/\\072/g; # may need to replace other symbols 5949 my $val2 = NetAddr::IP->new($val); 5950 print $datafile "'"._ZONE($val2, 'ZONE', 'r', '.').($val2->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'). 5951 ":$host:$ttl:$stamp:$loc\n" or die $!; 5952 } 5950 5953 5951 5954 # by-hand TXT … … 5966 5969 #:3600 5967 5970 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 5971 } elsif ($typemap{$type} eq 'CNAME') { 5972 5973 if ($revrec eq 'n') { 5974 print $datafile "C$host:$val:$ttl:$stamp:$loc\n" or die $!; 5975 } else { 5976 my $val2 = NetAddr::IP->new($val); 5977 print $datafile "C"._ZONE($val2, 'ZONE', 'r', '.').($val2->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'). 5978 ":$host:$ttl:$stamp:$loc\n" or die $!; 5979 } 5980 5981 } elsif ($typemap{$type} eq 'SRV') { 5982 5983 # data is two-byte values for priority, weight, port, in that order, 5984 # followed by length/string data 5985 5986 print $datafile ":$host:33:".octalize($dist,'d').octalize($weight,'d').octalize($port,'d') or die $!; 5987 5988 $val .= '.' if $val !~ /\.$/; 5989 foreach (split /\./, $val) { 5990 printf $datafile "\\%0.3o%s", length($_), $_ or die $!; 5991 } 5992 print $datafile "\\000:$ttl:$stamp:$loc\n" or die $!; 5993 5994 } elsif ($typemap{$type} eq 'RP') { 5995 5996 # RP consists of two mostly free-form strings. 5997 # The first is supposed to be an email address with @ replaced by . (as with the SOA contact) 5998 # The second is the "hostname" of a TXT record with more info. 5999 my $prefix = ":$host:17:"; 6000 my ($who,$what) = split /\s/, $val; 6001 foreach (split /\./, $who) { 6002 $prefix .= sprintf "\\%0.3o%s", length($_), $_; 6003 } 6004 $prefix .= '\000'; 6005 foreach (split /\./, $what) { 6006 $prefix .= sprintf "\\%0.3o%s", length($_), $_; 6007 } 6008 print $datafile "$prefix\\000:$ttl:$stamp:$loc\n" or die $!; 6009 6010 } elsif ($typemap{$type} eq 'PTR') { 6011 6012 $zone = NetAddr::IP->new($zone); 6013 $$recflags{$val}++; 6014 if (!$zone->{isv6} && $zone->masklen > 24) { 6015 ($val) = ($val =~ /\.(\d+)$/); 6016 print $datafile "^$val."._ZONE($zone, 'ZONE', 'r', '.').'.in-addr.arpa'. 6017 ":$host:$ttl:$stamp:$loc\n" or die $!; 6018 } else { 6019 $val = NetAddr::IP->new($val); 6020 print $datafile "^". 6021 _ZONE($val, 'ZONE', 'r', '.').($val->{isv6} ? '.ip6.arpa' : '.in-addr.arpa'). 6022 ":$host:$ttl:$stamp:$loc\n" or die $!; 6023 } 6024 6025 } elsif ($type == 65280) { # A+PTR 6026 6027 $$recflags{$val}++; 6028 print $datafile "=$host:$val:$ttl:$stamp:$loc\n" or die $!; 6029 6030 } elsif ($type == 65281) { # AAAA+PTR 6031 6032 $$recflags{$val}++; 6033 # treat these as two separate records. since tinydns doesn't have 6034 # a native combined type, we have to create them separately anyway. 6035 # print both; a dangling record is harmless, and impossible via web 6036 # UI anyway 6037 _printrec_tiny($datafile,$revrec,$recflags,$zone,$host,28,$val,$dist,$weight,$port,$ttl,$loc,$stamp); 6038 _printrec_tiny($datafile,$revrec,$recflags,$zone,$host,12,$val,$dist,$weight,$port,$ttl,$loc,$stamp); 6036 6039 ##fixme: add a config flag to indicate use of the patch from http://www.fefe.de/dns/ 6037 6040 # type 6 is for AAAA+PTR, type 3 is for AAAA 6038 6041 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6042 } elsif ($type == 65282) { # PTR template 6043 6044 # only useful for v4 with standard DNS software, since this expands all 6045 # IPs in $zone (or possibly $val?) with autogenerated records 6046 $val = NetAddr::IP->new($val); 6047 return if $val->{isv6}; 6048 6049 if ($val->masklen <= 16) { 6050 foreach my $sub ($val->split(16)) { 6051 __publish_subnet($sub, $recflags, $host, $datafile, $ttl, $stamp, $loc, 1); 6052 } 6053 } else { 6054 __publish_subnet($val, $recflags, $host, $datafile, $ttl, $stamp, $loc, 1); 6055 } 6056 6057 } elsif ($type == 65283) { # A+PTR template 6058 6059 $val = NetAddr::IP->new($val); 6060 # Just In Case. An A+PTR should be impossible to add to a v6 revzone via API. 6061 return if $val->{isv6}; 6062 6063 if ($val->masklen <= 16) { 6064 foreach my $sub ($val->split(16)) { 6065 __publish_subnet($sub, $recflags, $host, $datafile, $ttl, $stamp, $loc, 0); 6066 } 6067 } else { 6068 __publish_subnet($val, $recflags, $host, $datafile, $ttl, $stamp, $loc, 0); 6069 } 6070 6071 } elsif ($type == 65284) { # AAAA+PTR template 6072 # Stub for completeness. Could be exported to DNS software that supports 6073 # some degree of internal automagic in generic-record-creation 6074 # (eg http://search.cpan.org/dist/AllKnowingDNS/ ) 6075 6076 } elsif ($type == 65285) { # Delegation 6077 # This is intended for reverse zones, but may prove useful in forward zones. 6078 6079 # All delegations need to create one or more NS records. The NS record handler knows what to do. 6080 _printrec_tiny($datafile,$revrec,$recflags,$zone,$host,$reverse_typemap{'NS'}, 6081 $val,$dist,$weight,$port,$ttl,$loc,$stamp); 6082 if ($revrec eq 'y') { 6083 # In the case of a sub-/24 v4 reverse delegation, we need to generate CNAMEs 6084 # to redirect all of the individual IP lookups as well. 6085 # Not sure how this would actually resolve if a /24 or larger was delegated 6086 # one way, and a sub-/24 in that >=/24 was delegated elsewhere... 6087 my $dblock = NetAddr::IP->new($val); 6088 if (!$dblock->{isv6} && $dblock->masklen > 24) { 6089 my @subs = $dblock->split; 6090 foreach (@subs) { 6091 next if $$recflags{"$_"}; 6092 my ($oct) = ($_->addr =~ /(\d+)$/); 6093 print $datafile "C"._ZONE($_, 'ZONE.in-addr.arpa', 'r', '.').":$oct.". 6094 _ZONE($dblock, 'ZONE.in-addr.arpa', 'r', '.').":$ttl:$stamp:$loc\n" or die $!; 6095 $$recflags{"$_"}++; 6096 } 6097 } 6098 } 6096 6099 6097 6100 ## … … 6099 6102 ## 6100 6103 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6104 } elsif ($type == 44) { # SSHFP 6105 my ($algo,$fpt,$fp) = split /\s+/, $val; 6106 6107 my $rec = sprintf ":$host:44:\\%0.3o\\%0.3o", $algo, $fpt; 6108 while (my ($byte) = ($fp =~ /^(..)/) ) { 6109 $rec .= sprintf "\\%0.3o", hex($byte); 6110 $fp =~ s/^..//; 6111 } 6112 print $datafile "$rec:$ttl:$stamp:$loc\n" or die $!; 6113 6114 } else { 6115 # raw record. we don't know what's in here, so we ASS-U-ME the user has 6116 # put it in correctly, since either the user is messing directly with the 6117 # database, or the record was imported via AXFR 6118 # <split by char> 6119 # convert anything not a-zA-Z0-9.- to octal coding 6117 6120 6118 6121 ##fixme: add flag to export "unknown" record types - note we'll probably end up 6119 6122 # mangling them since they were written to the DB from Net::DNS::RR::<type>->rdatastr. 6120 6121 6122 6123 #print $datafile ":$host:$type:$val:$ttl:$stamp:$loc\n"; 6124 6125 } # record type if-else 6123 6126 6124 6127 } # end _printrec_tiny()
Note:
See TracChangeset
for help on using the changeset viewer.