-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathaggregate-by-asn.pl
executable file
·84 lines (73 loc) · 1.8 KB
/
aggregate-by-asn.pl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#!/usr/bin/perl -w
use strict;
use Net::IP; # libnet-ip-perl
my %as;
while (<>) {
my ($pref, $asn) = split;
push(@{$as{$asn}}, $pref);
}
foreach my $asn (keys %as) {
if (scalar @{$as{$asn}} <= 1) {
print @{$as{$asn}}[0] . " $asn\n";
next;
}
my @nets = map { Net::IP->new($_) or die "Not an IP: $_" } @{$as{$asn}};
sort_networks(\@nets);
#remove_overlaps(\@nets);
aggregate(\@nets);
print $_->prefix . " $asn\n" foreach @nets;
}
exit 0;
sub sort_networks {
my $addrs = $_[0];
@$addrs = sort {
$a->bincomp('lt', $b) ? -1 : ($a->bincomp('gt', $b) ? 1 : 0);
} @$addrs;
}
# this function is unfinished...
sub aggregate {
my $addrs = $_[0];
# continue aggregating until there are no more changes to do
my $changed = 1;
while ($changed) {
$changed = 0;
my @new_addrs;
my $prev = $addrs->[0];
foreach my $cur (@$addrs[1 .. $#{$addrs}]) {
if (my $aggregated = $prev->aggregate($cur)) {
$prev = $aggregated;
$changed = 1;
} else {
push(@new_addrs, $prev);
$prev = $cur;
}
}
push(@new_addrs, $prev);
@$addrs = @new_addrs;
}
}
sub remove_overlaps {
my $addrs = $_[0];
my @nets;
my $prev = $addrs->[0];
foreach my $cur (@$addrs[1..$#{$addrs}]) {
my $how = $prev->overlaps($cur);
if ($how == $IP_NO_OVERLAP) {
push(@nets, $prev);
} elsif ($how == $IP_A_IN_B_OVERLAP) { # cur contains prev
warn "A IN B p:".$prev->prefix." c:".$cur->prefix."\n";
push(@nets, $prev);
} elsif ($how == $IP_B_IN_A_OVERLAP) { # prev contains cur
warn "B IN A p:".$prev->prefix." c:".$cur->prefix."\n";
push(@nets, $prev);
} elsif ($how == $IP_IDENTICAL) {
# } elsif ($how == $IP_PARTIAL_OVERLAP) {
} else {
warn "Error: " . $prev->prefix . " overlaps " . $cur->prefix
. " ($how).\n";
# push(@nets, $prev); # ???
}
$prev = $cur;
}
@$addrs = @nets;
}