mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-05 12:16:38 +02:00

"fetch" sounds a bit like "download", but that is not what this utility does. Calling it "query" seems more appropriate.
96 lines
2.0 KiB
Perl
Executable File
96 lines
2.0 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
#
|
|
# Utility to query GeoIP database (.iv4/.iv6 files)
|
|
# Copyright Philip Prindeville, 2018
|
|
#
|
|
use Getopt::Long;
|
|
use Socket qw(AF_INET AF_INET6 inet_ntop);
|
|
use warnings;
|
|
use strict;
|
|
|
|
sub AF_INET_SIZE() { 4 }
|
|
sub AF_INET6_SIZE() { 16 }
|
|
|
|
my $target_dir = ".";
|
|
my $ipv4 = 0;
|
|
my $ipv6 = 0;
|
|
|
|
&Getopt::Long::Configure(qw(bundling));
|
|
&GetOptions(
|
|
"D=s" => \$target_dir,
|
|
"4" => \$ipv4,
|
|
"6" => \$ipv6,
|
|
);
|
|
|
|
if (!-d $target_dir) {
|
|
print STDERR "Target directory $target_dir does not exit.\n";
|
|
exit 1;
|
|
}
|
|
|
|
# if neither specified, assume both
|
|
if (! $ipv4 && ! $ipv6) {
|
|
$ipv4 = $ipv6 = 1;
|
|
}
|
|
|
|
foreach my $cc (@ARGV) {
|
|
if ($cc !~ m/^([a-z]{2}|a[12]|o1)$/i) {
|
|
print STDERR "Invalid country code '$cc'\n";
|
|
exit 1;
|
|
}
|
|
|
|
my $file = $target_dir . '/' . uc($cc) . '.iv4';
|
|
|
|
if (! -f $file) {
|
|
printf STDERR "Can't find data for country '$cc'\n";
|
|
exit 1;
|
|
}
|
|
|
|
my ($contents, $buffer, $bytes, $fh);
|
|
|
|
if ($ipv4) {
|
|
open($fh, '<', $file) || die "Couldn't open file for '$cc'\n";
|
|
|
|
binmode($fh);
|
|
|
|
while (($bytes = read($fh, $buffer, AF_INET_SIZE * 2)) == AF_INET_SIZE * 2) {
|
|
my ($start, $end) = unpack('a4a4', $buffer);
|
|
$start = inet_ntop(AF_INET, $start);
|
|
$end = inet_ntop(AF_INET, $end);
|
|
print $start, '-', $end, "\n";
|
|
}
|
|
close($fh);
|
|
if (! defined $bytes) {
|
|
printf STDERR "Error reading file for '$cc'\n";
|
|
exit 1;
|
|
} elsif ($bytes != 0) {
|
|
printf STDERR "Short read on file for '$cc'\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
|
|
substr($file, -1) = '6';
|
|
|
|
if ($ipv6) {
|
|
open($fh, '<', $file) || die "Couldn't open file for '$cc'\n";
|
|
|
|
binmode($fh);
|
|
|
|
while (($bytes = read($fh, $buffer, AF_INET6_SIZE * 2)) == AF_INET6_SIZE * 2) {
|
|
my ($start, $end) = unpack('a16a16', $buffer);
|
|
$start = inet_ntop(AF_INET6, $start);
|
|
$end = inet_ntop(AF_INET6, $end);
|
|
print $start, '-', $end, "\n";
|
|
}
|
|
close($fh);
|
|
if (! defined $bytes) {
|
|
printf STDERR "Error reading file for '$cc'\n";
|
|
exit 1;
|
|
} elsif ($bytes != 0) {
|
|
printf STDERR "Short read on file for '$cc'\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit 0;
|