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