#!/usr/bin/perl -Tw # [MJS 22 Oct 2001] Aggregate CIDR addresses # [MJS 9 Oct 2007] Overlap idea from Anthony Ledesma at theplanet dot com. use strict; use Net::IP; ## Read in all the IP addresses from <> my @addrs = map { new Net::IP $_ or die "Not an IP: \"$_\"."; } map { /^\s*(.*?)\s*$/ and $1; } <>; ## Sort the IP addresses @addrs = sort { $a->bincomp( 'lt', $b ) ? -1 : ( $a->bincomp( 'gt', $b ) ? 1 : 0 ); } @addrs; ## Handle overlaps my $count = 0; my $current = $addrs[0]; foreach my $next ( @addrs[ 1 .. $#addrs ] ) { my $r = $current->overlaps($next); if ( $r == $IP_NO_OVERLAP ) { $current = $next; $count++; } elsif ( $r == $IP_A_IN_B_OVERLAP ) { $current = $next; splice( @addrs, $count, 1 ); } elsif ( $r == $IP_B_IN_A_OVERLAP or $r == $IP_IDENTICAL ) { splice( @addrs, $count + 1, 1 ); } else { die "$0: internal error - overlaps() returned an unexpected value!\n"; } } ## Keep aggregating until we don't change anything my $change = 1; while ($change) { $change = 0; my @new_addrs = (); my $current = $addrs[0]; foreach my $next ( @addrs[ 1 .. $#addrs ] ) { if ( my $total = $current->aggregate($next) ) { $current = $total; $change = 1; } else { push @new_addrs, $current; $current = $next; } } push @new_addrs, $current; @addrs = @new_addrs; } ## Print out the IP addresses foreach (@addrs) { print $_->prefix(), "\n"; } # $Id: aggregate-cidr-addresses,v 1.3 2008/05/17 07:00:42 suter Exp $