Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Splitting IP ranges depending on overlap conditions

by kamesh3183 (Beadle)
on Apr 14, 2006 at 11:31 UTC ( [id://543317]=perlquestion: print w/replies, xml ) Need Help??

kamesh3183 has asked for the wisdom of the Perl Monks concerning the following question:

Hi,
Background: I have two lists (L1 & L2) each containing an IP range and information about them(like country, state, zip..etc). List L1 is dynamically generated and it can contain more than 10 million records. L2 has 50-100 records. It is not necessary that these IP ranges are valid IP blocks. I have to iterate through the list L1 and check whether any of the IP range overlaps with any range in the L2 and if it overlaps, then substitute the information of L1 with L2 for matching range only(If the range does not overlaps completely then i need to split the range of L1). for example take a simple case; if current L1 record is 81.68.0.0 - 81.68.0.20, xyz and L2 record is 81.68.0.0 - 81.68.0.10, abc

L1 recors must be splitted into 81.68.0.0 - 81.68.0.10, abc and 81.68.0.11 - 81.68.0.20, xyz

I have gone through Net::IP module and found that it can used for testing overlap conditions but I am not sure about splitting ranges.
my $V_IP = new Net::IP('81.0.0.0 - 84.23.45.67') or die( Net::IP::Erro +r() ); my $G_IP = new Net::IP('80.60.80.120 - 85.34.45.56') or die( Net::IP:: +Error() ); my $V_Match = $G_IP->overlaps($V_IP); if (not defined($V_Match)) { print "Problem with IP range\n"; } elsif ( $V_Match == $IP_IDENTICAL ) { print $G_IP->print(), ' is identical with the range ', $V_ +IP->print(), "\n"; } elsif ( $V_Match == $IP_A_IN_B_OVERLAP ) { print $V_IP->print(), ' contains the range ', $G_IP->print +(), "\n"; } elsif ( $V_Match == $IP_B_IN_A_OVERLAP ) { print $G_IP->print(), ' contains the range ', $V_IP->print +(), "\n"; } elsif ( $V_Match == $IP_PARTIAL_OVERLAP ) { print $G_IP->print(), ' partially overlaps with the range +', $V_IP->print(), "\n"; } elsif ( $V_Match == $IP_NO_OVERLAP ) { print $V_IP->print(), ' doesnot overlap with ', $G_IP->pri +nt(), "\n"; }
Could you please tell is there any module on CPAN that can do this thing?

Thanks
Kamesh

Replies are listed 'Best First'.
Re: Splitting IP ranges depending on overlap conditions
by kvale (Monsignor) on Apr 14, 2006 at 15:35 UTC
    I don't know of any modules that do exactly as you want with IP addresses. But it is useful to note that IPv4 addresses can be packed into a 32 bit integer, so ranges of IP adresses can be mapped into ranges of integers. Then you may use a module called Set::IntSpan to manipulate ranges to your hearts content:
    use Set::IntSpan qw(grep_set map_set); $Set::IntSpan::Empty_String = $string; $set = new Set::IntSpan $set_spec; $valid = valid Set::IntSpan $run_list; $set = copy $set $set_spec; $run_list = run_list $set; @elements = elements $set; @spans = spans $set; $u_set = union $set $set_spec; $i_set = intersect $set $set_spec; $x_set = xor $set $set_spec; $d_set = diff $set $set_spec; $c_set = complement $set; # and many more methods
    Also there are the modules Array::IntSpan and Array::IntSpan::IP which also manipulate ranges in an array context, but don't seem quite as flexible as Set::IntSpan.

    -Mark

Re: Splitting IP ranges depending on overlap conditions
by eXile (Priest) on Apr 14, 2006 at 15:26 UTC
    I'm not aware of a CPAN module that can do this.

    You could convert your dotted-quad IP-addresses to integers, so you can do some simple math with them:

    if ( $ip =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ ) { $number = $1 >> 24 + $2 >> 16 + $3 >> 8 + $4 }

      TMTOWTDI, and I normally do this sort of thing:

      use strict; use warnings; use Socket qw{ inet_aton inet_ntoa }; sub ip_to_num { unpack( 'N', inet_aton( shift )); } sub ip_to_str { inet_ntoa( pack( 'N', shift )); } sub ip_plus { ip_to_str( ip_to_num( $_[0] ) + $_[1] ); } sub ip_minus { ip_plus( $_[0], -$_[1] ); } my $dotted_quad = '10.198.9.2'; print ip_plus( $dotted_quad, 290 ), "\n"; print ip_minus( $dotted_quad, 3 ), "\n"; __END__ 10.198.10.36 10.198.8.255

      In the OPs case, he only needs to add 1 and subtract 1. Again, all of this craps out on IPv6. I suspect that isn't a concern yet.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://543317]
Approved by herveus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (3)
As of 2024-04-20 08:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found