#!/usr/bin/perl # $Header: /u/cvsroot/tinydns-fixup/tinydns-fixup.pl,v 1.5 2005/05/10 17:02:38 mayoff Exp $ use strict; my %ipMap; open(IN, $ARGV[0]) || die "$ARGV[0]: $!\n"; seek(IN, 0, 0) || die "could not seek: $!; input must be a regular file\n"; while () { chomp; my $type = substr($_, 0, 1); substr($_, 0, 1) = ""; my %fields; next if (!getFields($type, $_, \%fields)); # Ignore wildcard FQDNs. next if (substr($fields{'name'}, 0, 1) eq '*'); # Ignore records that don't have real IP addresses. next if ($fields{'ip'} !~ /^\d+\.\d+\.\d+\.\d+$/); if (exists $ipMap{"$fields{'name'}:$fields{'lo'}"}) { print STDERR "warning: redefinition of $fields{'name'}:$fields{'lo'} ignored\n"; } else { $ipMap{"$fields{'name'}:$fields{'lo'}"} = $fields{'ip'}; } } seek(IN, 0, 0) || die "could not seek: $!; input must be a regular file\n"; while () { chomp; my $type = substr($_, 0, 1); my $rest = substr($_, 1); my %fields; if ( getFields($type, $rest, \%fields) && $fields{'ip'} !~ /^(\d+\.\d+\.\d+\.\d+)$/ ) { my $newIP = $fields{'ip'}; if (exists $ipMap{"$fields{'ip'}:$fields{'lo'}"}) { $newIP = $ipMap{"$fields{'ip'}:$fields{'lo'}"}; } elsif (exists $ipMap{"$fields{'ip'}:"}) { $newIP = $ipMap{"$fields{'ip'}:"}; } my ($typeFqdn, $colon1, $ip, $colon2, $rest) = split(/(:)/, $_, 3); $_ = qq($typeFqdn$colon1$newIP$colon2$rest); } print $_, "\n"; } exit(0); sub getFields { my ($type, $rest, $fieldsRef) = @_; my @fields = split(/:/, $rest); if ($type eq '.' || $type eq '&') { @{$fieldsRef}{'fqdn','ip','x','ttl','timestamp','lo'} = @fields; if (index($fieldsRef->{'x'}, '.') < 0) { $fieldsRef->{'name'} = "$fieldsRef->{'x'}.ns.$fieldsRef->{'fqdn'}"; } else { $fieldsRef->{'name'} = $fieldsRef->{'x'}; } } elsif ($type eq '=' || $type eq '+' || $type eq '-') { @{$fieldsRef}{'name','ip','ttl','timestamp','lo'} = @fields; } elsif ($type eq '@') { @{$fieldsRef}{'fqdn','ip','x','dist','ttl','timestamp','lo'} = @fields; if (index($fieldsRef->{'x'}, '.') < 0) { $fieldsRef->{'name'} = "$fieldsRef->{'x'}.mx.$fieldsRef->{'fqdn'}"; } else { $fieldsRef->{'name'} = $fieldsRef->{'x'}; } } else { return 0; } return 1; } __END__ =head1 NAME tinydns-fixup - Substitute addresses for names in tinydns data =head1 SYNOPSIS B data.f > data =head1 DESCRIPTION I reads I. For each ".", "&", "=", "+", "-", or "@" record that associates a name with an IP address, I stores the IP address in a hash table with the name as the key. If the record contains a location code, then the location code is also part of the key. I then reads I a second time. For each ".", "&", "=", "+", "-", or "@" record that contains a name where it should contain an IP address, I looks up the name in its hash table. If the record contains a location code, then the location code is also used in the lookup. If the name (and location) is in the table, I substitutes the IP address for the name in the record. I then prints the record (regardless of whether it performed a substitution). If I could not find the name and location in the table, then it tries again with just the name. The input data file must be seekable; a named pipe will not work. =head1 AUTHOR Rob Mayoff =head1 VERSION $Id: tinydns-fixup.pl,v 1.5 2005/05/10 17:02:38 mayoff Exp $ =cut