Index: lib/GeoDNS.pm =================================================================== --- lib/GeoDNS.pm (Revision 687) +++ lib/GeoDNS.pm (Arbeitskopie) @@ -101,21 +101,21 @@ if ($data->{$label}) { my @hosts; - if ($query_type =~ m/^(A|ANY|TXT)$/x) { + if ($query_type =~ m/^(A|AAAA|ANY|TXT)$/x) { my (@groups) = $self->pick_groups($config_base, $peer_host, $label); for my $group (@groups) { - push @hosts, $self->pick_hosts($config_base, $group); + push @hosts, $self->pick_hosts($config_base, $group, $query_type); last if @hosts; # add ">= 2" to force at least two hosts even if the second one won't be as local } } - if ($query_type eq 'A' or $query_type eq 'ANY') { + if ($query_type eq 'A' or $query_type eq 'AAAA' or $query_type eq 'ANY') { for my $host (@hosts) { push @ans, Net::DNS::RR->new( name => $domain, ttl => $ttl, - type => 'A', + type => $host->{rtype}, address => $host->{ip} ); } @@ -215,10 +215,10 @@ } sub pick_hosts { - my ($self, $config_base, $group_name) = @_; + my ($self, $config_base, $group_name, $qtype) = @_; my $group = $config_base->{data}->{$group_name}; - return unless $group and $group->{a}; + return unless $group and $group->{$qtype}; my @answer; my $max = $config_base->{max_hosts} || 2; @@ -229,7 +229,7 @@ # find total weight; my $total = 0; my @servers = (); - for (sort { $a->[1] <=> $b->[1] } @{$group->{a}}) { + for (sort { $a->[1] <=> $b->[1] } @{$group->{$qtype}}) { $total += $_->[1]; push @servers, [0,$_]; } @@ -263,9 +263,17 @@ my $hostname = $host->[0]; - my $ip = $hostname =~ m/^\d{1,3}(.\d{1,3}){3}$/x ? $hostname : $config_base->{hosts}->{$hostname}->{ip}; - - push @answer, ({ name => $hostname, ip => $ip, weight => $host->[1] }); + my ($ip, $rtype); + if ($hostname =~ m/^\d{1,3}(.\d{1,3}){3}$/x) { + $ip = $hostname; + $rtype = "A"; + } else { + $ip = $config_base->{hosts}->{$hostname}->{ip}; + $rtype = $config_base->{hosts}->{$hostname}->{rtype}; + } + + push @answer, ({ name => $hostname, ip => $ip, rtype => $rtype, + weight => $host->[1] }); } map { $_->[0] = 0 } @picked; @@ -428,11 +436,23 @@ my ($host, $ip, $groups) = split(/\s+/,$_,3); die "Bad configuration line: [$_]\n" unless $groups; $host = "$host." unless $host =~ m/\.$/; - $config_base->{hosts}->{$host} = { ip => $ip }; + my $rtype = "A"; + if ($ip =~ m/:/){ + $rtype = "AAAA"; + $ip = _normalize_AAAA($ip); + } + $config_base->{hosts}->{$host} = { ip => $ip, rtype => $rtype }; for my $group_name (split /\s+/, $groups) { $group_name = '' if $group_name eq '@'; - $config_base->{data}->{$group_name}->{a} ||= []; - push @{$config_base->{data}->{$group_name}->{a}}, [ $host, 1 ]; + # Add the host to it's group, according to querty type + $config_base->{data}->{$group_name}->{$rtype} ||= []; + push @{$config_base->{data}->{$group_name}->{$rtype}}, [ $host, 1 ]; + # Also add each host to the TXT block + $config_base->{data}->{$group_name}->{TXT} ||= []; + push @{$config_base->{data}->{$group_name}->{TXT}}, [ $host, 1 ]; + # Also add each host to the ANY block + $config_base->{data}->{$group_name}->{ANY} ||= []; + push @{$config_base->{data}->{$group_name}->{ANY}}, [ $host, 1 ]; } } } @@ -454,6 +474,33 @@ return 1; } +sub _normalize_AAAA { + # This is taken from DNS::RR::AAAA::new_from_string + # Unfortunately, AAAA.pm does not perform this algorithm + # for records created from a hash + my $string = shift; + if ($string =~ /^(.*):(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { + my ($front, $a, $b, $c, $d) = ($1, $2, $3, $4, $5); + $string = $front . sprintf(":%x:%x", + ($a << 8 | $b), + ($c << 8 | $d)); + } + + if ($string =~ /^(.*)::(.*)$/) { + my ($front, $back) = ($1, $2); + my @front = split(/:/, $front); + my @back = split(/:/, $back); + my $fill = 8 - (@front ? $#front + 1 : 0) + - (@back ? $#back + 1 : 0); + my @middle = (0) x $fill; + my @addr = (@front, @middle, @back); + $string = sprintf("%x:%x:%x:%x:%x:%x:%x:%x", + map { hex $_ } @addr); + } + return $string; +} + + 1;