From f180c0e5c6026c44481607fcbe9f9bd3f4ed702e Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Tue, 4 Jan 2011 03:49:44 +0100 Subject: [PATCH] geoipdb tools: IPv6 support --- geoip/xt_geoip_build | 60 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/geoip/xt_geoip_build b/geoip/xt_geoip_build index 5016ff3..933bc17 100755 --- a/geoip/xt_geoip_build +++ b/geoip/xt_geoip_build @@ -1,7 +1,7 @@ #!/usr/bin/perl # # Converter for MaxMind CSV database to binary, for xt_geoip -# Copyright © Jan Engelhardt , 2008 +# Copyright © Jan Engelhardt , 2008-2011 # # Use -b argument to create big-endian tables. # @@ -11,7 +11,11 @@ use Text::CSV_XS; # or trade for Text::CSV use strict; my %country; -my $csv = Text::CSV_XS->new({binary => 0, eol => $/}); # or Text::CSV +my $csv = Text::CSV_XS->new({ + allow_whitespace => 1, + binary => 1, + eol => $/, +}); # or Text::CSV my $target_dir = "."; &Getopt::Long::Configure(qw(bundling)); @@ -36,10 +40,16 @@ while (my $row = $csv->getline(*ARGV)) { $country{$row->[4]} = { name => $row->[5], pool_v4 => [], + pool_v6 => [], }; } - my $c = $country{$row->[4]}{pool_v4}; - push(@$c, [$row->[2], $row->[3]]); + my $c = $country{$row->[4]}; + if ($row->[0] =~ /:/) { + push(@{$c->{pool_v6}}, + [&ip6_pack($row->[0]), &ip6_pack($row->[1])]); + } else { + push(@{$c->{pool_v4}}, [$row->[2], $row->[3]]); + } if ($. % 4096 == 0) { print STDERR "\r\e[2K$. entries"; } @@ -50,6 +60,27 @@ print STDERR "\r\e[2K$. entries total\n"; foreach my $iso_code (sort keys %country) { my($file, $fh_le, $fh_be); + printf "%5u IPv6 ranges for %s %s\n", + scalar(@{$country{$iso_code}{pool_v6}}), + $iso_code, $country{$iso_code}{name}; + + $file = "$target_dir/LE/".uc($iso_code).".iv6"; + if (!open($fh_le, "> $file")) { + print STDERR "Error opening $file: $!\n"; + exit 1; + } + $file = "$target_dir/BE/".uc($iso_code).".iv6"; + if (!open($fh_be, "> $file")) { + print STDERR "Error opening $file: $!\n"; + exit 1; + } + foreach my $range (@{$country{$iso_code}{pool_v6}}) { + print $fh_be $range->[0], $range->[1]; + print $fh_le &ip6_swap($range->[0]), &ip6_swap($range->[1]); + } + close $fh_le; + close $fh_be; + printf "%5u IPv4 ranges for %s %s\n", scalar(@{$country{$iso_code}{pool_v4}}), $iso_code, $country{$iso_code}{name}; @@ -71,3 +102,24 @@ foreach my $iso_code (sort keys %country) { close $fh_le; close $fh_be; } + +sub ip6_pack +{ + my $addr = shift @_; + $addr =~ s{::}{:!:}; + my @addr = split(/:/, $addr); + my @e = (0) x 8; + foreach (@addr) { + if ($_ eq "!") { + $_ = join(':', @e[0..(8-scalar(@addr))]); + } + } + @addr = split(/:/, join(':', @addr)); + $_ = hex($_) foreach @addr; + return pack("n*", @addr); +} + +sub ip6_swap +{ + return pack("V*", unpack("N*", shift @_)); +}