- Timestamp:
- 11/24/20 14:00:26 (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/bind2hosts
r806 r807 33 33 my $skipfile; 34 34 my $dryrun = 0; 35 # CNAME chain depth 36 my $maxdepth = 3; 35 37 36 38 GetOptions( … … 50 52 octet-reversed form. Specify multiple times to skip multiple 51 53 different record patterns. 52 --skip -file54 --skipfile 53 55 A file containing patterns to skip. Patterns from the file and 54 56 any --skip arguments are merged. … … 84 86 my $dnsdb = new DNSDB; 85 87 86 ##fixme: retrieve defttl from SOA record87 #my $zonettl = 900;88 #my $defttl = $zonettl;89 88 # need an ultimate fallback for this one 90 89 my $defttl = 900; … … 101 100 next if $rec =~ /^\s*;/; 102 101 next if $rec =~ /^\s*\)/; # SOA closing (possibly other records too?) 103 # arguably should do some more targeted voodoo when parsing the SOA details 104 #print "$i: ($rec)\n"; 105 #last if ++$i > 5; 102 # arguably should do some more targeted voodoo when parsing the SOA details 106 103 107 104 my $skipflag = 0; 108 105 foreach (@skipdefs) { 109 #print "skipdbg: $_ =~ $rec\n" if $rec =~ /207/;110 106 if ($rec =~ /\Q$_\E/) { 111 107 $skipflag = 1; 112 # print "skip: $rec\n"; 108 # might want to do something with the skipped records someday 113 109 } 114 110 } … … 138 134 my $origrec = $rec; 139 135 140 ##fixme: convert to optional skipfile?141 # skip stale records that have no value142 #next if /^ip-\d+-\d+-\d+/;143 #next if /^ip.pre.fix.\d+.static.colo/;144 145 136 # leading whitespace indicates "same label as last record" 146 137 if ($rec =~ /^\s/) { … … 167 158 $rec =~ s/^([\w\@_.-]*)\s+//; 168 159 160 # now that we've collected and trimmed off the record's label, unpack the class, TTL, and type. 161 # class and TTL may be omitted, and may appear in either class,TTL or TTL,class order. 169 162 my $nc = 0; 170 163 my %seenatoms; … … 176 169 my $badrec; 177 170 my $curatom = 'class'; 178 179 # now that we've collected and trimmed off the record's label, unpack the class, TTL, and type.180 # class and TTL may be omitted, and may appear in either class,TTL or TTL,class order.181 171 eval { 182 172 for (; $nc < 3; $nc++) { … … 204 194 $class = $atom; 205 195 } 206 elsif ($atom =~ /^[A-Z ]+/) {196 elsif ($atom =~ /^[A-Z\d-]+/) { 207 197 # check against dnsadmin's internal list of known DNS types. 208 198 if ($reverse_typemap{$atom}) { … … 221 211 } 222 212 223 224 213 $ttl = $defttl if !defined($ttl); 225 214 226 my $itype = $reverse_typemap{$type};215 # Just In Case we need the original rdata after we've sliced off more pieces 227 216 my $rdata = $rec; 228 229 217 $prevlabel = $curlabel; 230 218 … … 237 225 # There are probably more efficient ways to do this but the SOA record 238 226 # format is essentially character based, not line-based. 239 # In theory the SOA serial etc may be spread over up to 5 lines, in any combination.227 # In theory the SOA serial etc may be spread over "many" lines, bounded by (). 240 228 241 229 # Parse fields from $rdata if present … … 266 254 elsif ($type eq 'A') { 267 255 # need the name->IP map so we can reverse-map the CNAMEs on output 268 # $amap{$curlabel}{$rdata}++;269 256 push @{$amap{$curlabel}}, $rdata; 270 # why doesn't this work? causes ALL cases of multi-named IPs to get skipped, not just duplicates. O_o271 # push @{$namemap{$rdata}}, $curlabel unless grep $curlabel, @{$namemap{$rdata}};272 # push @{$namemap{$rdata}}, $curlabel;# unless grep $curlabel, @{$namemap{$rdata}};273 257 $namemap{$rdata}{$curlabel}++; 274 275 258 } # A record 276 259 277 260 elsif ($type eq 'CNAME') { 278 ##todo: expand $rdata with $origin if unqualified279 261 $cmap{$curlabel} = $rdata.($rdata =~ /\./ ? '' : ".$origin"); 280 262 } # CNAME record … … 284 266 } # <STDIN> 285 267 286 287 288 289 268 #print Dumper \%cmap; 290 269 291 while (my ($cn, $targ) = each %cmap) { 270 # Walk the CNAME list and see if we can match the targets in-zone. 271 # Out-of-zone CNAMEs are out of scope for this conversion. 272 foreach my $cn (sort keys %cmap) { 273 my $targ = $cmap{$cn}; 292 274 #print "dbg: ".Dumper($targ); 293 if (!$amap{$targ}) { 294 if ($cmap{$targ}) { 295 warn "chained cname $cn => $targ\n"; 296 my $tmpcn = $targ; 297 $targ = $cmap{$tmpcn}; 298 warn " chain target $cn => $tmpcn => $targ\n"; 299 # next if !$amap{$targ}; 300 if (!$amap{$targ}) { 301 if ($cmap{$targ}) { 302 #print " second chain?\n"; 303 $tmpcn = $targ; 304 $targ = $cmap{$tmpcn}; 305 } else { 306 #print "not found\n"; 307 next; 308 } 309 } 310 } else { 311 # skip depth-3 (?) CNAMES; any such zone does not belong as a hosts file anyway 312 warn "CNAME $cn => $targ not found\n"; 313 next; 314 } 315 } 316 # print Dumper (\%{$amap{$cmap{$cn}}}); 317 # print "$cn -> $cmap{$cn}\n"; 318 # $amap{$cmap{$cn}}{$cn}++ if $cmap{$cn} =~ /$zname.$/ && $amap{$cmap{$cn}}; 319 # print "dangling CNAME $cn\n" if !$namemap{$cmap{$cn}}; 320 # print "$cn -> $cmap{$cn}\n"; 321 # warn "CNAME $cn out of zone\n" if !$namemap{$cn}; 322 my $targip = $amap{$targ}[0]; 323 #print "$cn => $targ\n" if $targ =~ /(webftp|landing)/; 324 #print $targip; 325 # push @{$namemap{$targip}}, $targ unless grep $targ, @{$namemap{$targip}}; 326 $namemap{$targip}{$cn}++;# unless grep $targ, @{$namemap{$targip}}; 327 } 275 my @targlist; 276 # push @targlist, $targ; # mostly for error reporting 277 my $dangle = 0; 278 279 my $depth = 1; # CNAME -> A 280 281 # check this as a loop for consistent fail/break conditions. bonus: may allow user choice for CNAME depth? 282 for (; $dangle == 0; $depth++) { 283 284 #print "d:$depth checking $cn -> $targ\n"; 285 push @targlist, $targ; 286 287 # Depth limit. If made user-selectable should arguably set a hard 288 # limit because deeply chained CNAMEs are Baaaaad, mmkaay? 289 if ($depth >= $maxdepth) { 290 warn "CNAMEs too deeply chained, skipping: $cn => ".join(' => ', @targlist)."\n"; 291 last; 292 } 293 294 # break if CNAME target is in the A record list 295 last if $amap{$targ}; 296 if ($cmap{$targ}) { 297 # note the new target 298 my $tmpcn = $targ; 299 $targ = $cmap{$tmpcn}; 300 #print " chaining $tmpcn to new $targ\n"; 301 } else { 302 # target is either out of zone or doesn't exist 303 $dangle = 1; 304 last; 305 } 306 307 308 #warn "chained cname $cn => $targ\n"; 309 # CNAME to another CNAME 310 #$tmpcn => $targ\n"; 311 312 # last if $dangle; 313 314 # if (!$amap{$targ}) { 315 # if ($cmap{$targ}) { 316 # $tmpcn = $targ; 317 # $targ = $cmap{$tmpcn}; 318 #push @targlist, $targ; 319 #warn " chain target $cn => ".join(' => ', @targlist). 320 # "\n"; 321 # } else { 322 # warn "skipping dangling CNAME $cn => $targlist[0] => $targlist[1]\n"; 323 # next; 324 # } 325 # } 326 # } else { 327 # # skip depth-3 (?) CNAMES; any such zone does not belong as a hosts file anyway 328 # warn "skipping dangling CNAME $cn => $targ\n"; 329 # next; 330 # } 331 # } 332 333 334 } # CNAME recursion loop 335 336 next if $dangle; 337 338 #print " chain target $cn => ".join(' => ', @targlist)."\n"; 339 if ($amap{$targ}) { 340 # absent any criteria, we use the first IP a name was associated with 341 my $targip = $amap{$targ}[0]; 342 $namemap{$targip}{$cn}++; 343 } else { 344 } 345 } # each %cmap 328 346 329 347 #print Dumper \%amap;
Note:
See TracChangeset
for help on using the changeset viewer.