Den 03. juni 2011 16:08, skrev Ask Bjørn Hansen:
Patches welcome: https://github.com/abh/ntppool/issues/17

Hi

Wrote some IPv6-stuff. Haven't run all of the code yet.

get_server_info will accept hostname, IPv4 or IPv6. Die if the IPv6 or IPv4-adress is part of a reserved address space. ip6_public_address does this, more invalid addresses can be added to the array inside the sub if needed. ip6_expand is used to fill in zeros in an address to an IPv6-address to allow converting it to a binary string for masking.

When resolving, the code chooses A-record first, and only checks for AAAA if A does not exist.

NTP.pm from CPAN needs to be modified to handle IPv6, just change IO::Socket::INET to IO::SOCKET::IP i guess.

The patch below is for Manage.pm. Only the subs ip6_public_address and ip6_expand are tested, but they might not work inside the package.

diff --git a/lib/NTPPool/Control/Manage.pm b/lib/NTPPool/Control/Manage.pm
index 1df3d01..26e2c85 100644
--- a/lib/NTPPool/Control/Manage.pm
+++ b/lib/NTPPool/Control/Manage.pm
@@ -10,7 +10,9 @@ use Email::Send 'SMTP';
 use Sys::Hostname qw(hostname);
 use Email::Date qw();
 use JSON::XS qw(encode_json);
-use Net::IPv6Addr;
+use Net::IP qw(ip_is_ipv6 ip_is_ipv4 ip_iptobin);
+use Net::DNS;
+use IO::Socket::IP; # For IPv6-support

 sub render {
     my $self = shift;
@@ -125,19 +127,28 @@ sub get_server_info {
     die "No hostname or IP\n" unless $host;

     my %server;
-    if (Net::IPv6Addr::ipv6_chkip($host)) {
+ if ($host !~ /^([0-9\.]+|[0-9a-f\:]+)$/) { # Check if host is IP-address
+        my $res = Net::DNS::Resolver->new;
+        $server{hostname} = $host;
+        my $iaddr; # FIXME!! Is IPv4 or IPv6 to have precedence?
+        die "Could resolve address for host $host\n" unless
+ $server{ip} = $res->query($host, 'A') or $server{ip} = $res->query($host, 'AAAA');
+    }
+    else {
         $server{ip} = $host;
+    }
+
+    if (ip_is_ipv6 ($server{ip})) {
         $server{ip_version} = 'v6';
+ die "IPv6-address is not public\n" unless ip6_public_address ($server{ip});
     }
-    else {
-        my $iaddr = gethostbyname $host;
-        die "Could not find the IP for $host\n" unless $iaddr;
-        $server{ip} = inet_ntoa($iaddr);
+    elsif (ip_is_ipv4 ($server{ip})) {
         $server{ip_version} = 'v4';
+ die "IPv4-address is not public\n" if $server{ip} =~ /^(127|10|192.168|0)\./;
+    }
+    else {
+        die "Bad IP address\n";
     }
-    $server{hostname} = $host if $host ne $server{ip};
-
-    die "Bad IP address\n" if $server{ip} =~ m/^(127|10|192.168|0)\./;

     if (my $s = NP::Model->server->fetch(ip => $server{ip})) {
         my $other =
@@ -153,12 +164,9 @@ sub get_server_info {
     warn "checking $host / $server{ip}";
     warn Data::Dumper->Dump([\%ntp]);

-    if ($server{ip_version} eq 'v4') {
- die "Didn't get an NTP response from $host\n" unless defined $ntp{Stratum};
-        die
- "Invalid stratum response from $host (Your server is in stratum $ntp{Stratum}). Is your server configured properly? Is public access allowed? If you just restarted your ntpd, then it might still be stabilizing the timesources - try again in 10-20 minutes.\n"
-          unless $ntp{Stratum} > 0 and $ntp{Stratum} < 6;
-    }
+ die "Didn't get an NTP response from $host\n" unless defined $ntp{Stratum}; + die "Invalid stratum response from $host (Your server is in stratum $ntp{Stratum}). Is your server configured properly? Is public access allowed? If you just restarted your ntpd, then it might still be stabilizing the timesources - try again in 10-20 minutes.\n"
+        unless $ntp{Stratum} > 0 and $ntp{Stratum} < 6;

     $server{ntp} = \%ntp;

@@ -177,6 +185,42 @@ sub get_server_info {
     return \%server;
 }

+sub ip6_expand { # Fill in zeros in an IPv6-address
+    my $ip = shift;
+    $ip =~ s/::/:FILL:/;
+    my @parts = split /:/, $ip;
+    my @parts_new;
+    foreach (@parts) {
+        if ($_ eq "FILL") {
+            my $j = 0;
+            until ($j > (8 - @parts)) {
+                push @parts_new, "0000";
+                $j++;
+            }
+        }
+        else {
+            my @tmp = split //;
+            unshift @tmp, "0" while @tmp < 4;
+            push @parts_new, join "", @tmp;
+        }
+    }
+    return join ":", @parts_new;
+}
+
+sub ip6_public_address { # Return 0 if IP is part of a reserved address space, 1 if not + my $ip_bin = ip_iptobin (ip6_expand (shift), 6) || die "Could not binarize IP6 address";
+    my @bad_nets = qw(fc00::/7 fe80::/10 ff00::/8);
+    foreach (@bad_nets) {
+        if (/^([0-9a-f\:]+)\/(\d+)$/i) {
+            my ($address, $mask) = (ip6_expand($1), $2);
+ my $net_bin = ip_iptobin ($address, 6) || die "Could not binarize IP6 address"; + my $ip_net = $ip_bin & ("1" x $mask . ("0" x (128 - $mask))); # Mask the IP
+            return 0 if ($ip_net eq $net_bin);
+        }
+    }
+    return 1;
+}
+
 sub req_server {
     my $self      = shift;
     my $server_id = $self->req_param('server');

Patch end

Atle.

_______________________________________________
pool mailing list
[email protected]
http://lists.ntp.org/listinfo/pool

Reply via email to