Noosrep
Noosrep

Reputation: 416

Loop over a range of IPs with perl IP library

I'm trying to create an IP table list where I can see which IPs are in use and which aren't.

I use the Net::IP library for this. Code snippet:

my @IPsinrange = &getAllIPs($range) ; #range is x.x.x.x/subnet format
sub getAllIPs {
    my $ip = new Net::IP ($range) || die;
    my @IPs ;
    # Loop
    do {
        push @IPs, $ip->ip() ;
    } while (++$ip);

    return @IPs ;   
}  

This works for a x.x.x.0/24 network and this works for 1.2.3.4/32 but when I use 1.2.3.4/29 for instance, the loop just dies. I thought it could be because of the fact that there were no IP adresses in use, but there are 4 IPs in that range that are alive.

Upvotes: 0

Views: 367

Answers (2)

Borodin
Borodin

Reputation: 126772

I suggest that you use the Net::CIDR function library instead. The function Net::CIDR::cidr2octets does exactly what you need, and doesn't insist that the base address for a range is the network address

Here's an example that uses your test data 1.2.3.4/29 for the range

use strict;
use warnings 'all';
use feature 'say';

use Net::CIDR;

my @range = Net::CIDR::cidr2octets('1.2.3.4/29');

say for @range;

output

1.2.3.0
1.2.3.1
1.2.3.2
1.2.3.3
1.2.3.4
1.2.3.5
1.2.3.6
1.2.3.7

If you want to "normalize" a CIDR block that may not use the network address as the prefix, you can use Net::CIDR::cidr2range followed by Net::CIDR::range2cidr. Given '1.2.3.4/29', the first returns 1.2.3.0-1.2.3.7, and when that result is passed into Net::CIDR::range2cidr we get a normalised result

Like so

Net::CIDR::range2cidr(Net::CIDR::cidr2range('1.2.3.4/29'));

output

1.2.3.0/29

Upvotes: 1

stevieb
stevieb

Reputation: 9306

The reason this isn't working is due to the fact that the module requires you to send in a proper network address as the starting point of a given IP prefix.

Since you want to use a /29 prefix, valid ranges would be:

1.2.3.0/29
1.2.3.8/29
1.2.3.16/29
...etc

As mentioned in the comments, the documentation states that the proper usage of the constructor to get proper diagnostic output is:

$ip = Net::IP->new('1.2.3.0/29') or die (Net::IP::Error());

Upvotes: 3

Related Questions