NAME

Net::IPAM::Block - A library for reading, formatting, sorting, ... and much more for IP-blocks.

SYNOPSIS

use Net::IPAM::Block;

# parse and normalize
$cidr  = Net::IPAM::Block->new('10.0.0.0/255.0.0.0') // die 'wrong format,';
$cidr  = Net::IPAM::Block->new('10.0.0.0/8')         // die 'wrong format,';
$range = Net::IPAM::Block->new('fe80::2-fe80::e')    // die 'wrong format,';
$host  = Net::IPAM::Block->new('2001:db8::1')        // die 'wrong format,';

DESCRIPTION

A block is an IP-network or IP-range, e.g.

192.168.0.1/255.255.255.0   # network, with IP mask
192.168.0.1/24              # network, with CIDR mask
::1/128                     # network, with CIDR mask
10.0.0.3-10.0.17.134        # range
2001:db8::1-2001:db8::f6    # range

The parsed block is represented as an object with:

base
last

This representation is fast sortable without conversions to/from the different IP versions.

METHODS

new

$b = Net::IPAM::Block->new('fe80::/10');

new() parses the input as CIDR, range or address (or IP object, see below) and returns the Net::IPAM::Block object.

Example for valid input strings:

2001:db8:dead::/38
10.0.0.0/8
10.0.0.0/255.0.0.0

2001:db8::1-2001:db8::ff00:35
192.168.2.3-192.168.7.255

If a begin-end range can be represented as a CIDR, new() calculates the netmask and returns the range as CIDR block with a proper mask.

Plain IP addresses as input strings or objects are converted to /32 or /128 CIDRs.

0.0.0.0                       => 0.0.0.0/32
::ffff:127.0.0.1              => 127.0.0.1/32
::                            => ::/128
Net::IPAM::IP->new('1.2.3.4') => 1.2.3.4/32


$range = Net::IPAM::Block->new('10.2.0.17-10.3.67.255') // die 'wrong block format,';
$range = Net::IPAM::Block->new('fe80::-fe80::1234')     // die 'wrong block format,';

$cidr_24  = Net::IPAM::Block->new('10.0.0.0/24') // die 'wrong block format,';
$cidr_32  = Net::IPAM::Block->new('192.168.0.1') // die 'wrong block format,';
$cidr_128 = Net::IPAM::Block->new('2001:db8::1') // die 'wrong block format,';

$cidr_128 = Net::IPAM::Block->new( Net::IPAM::IP->new('2001:db8::1') // die 'wrong IP format,' );

Returns undef on illegal input.

version

$v = $b->version

Returns 4 or 6.

to_string

Returns the block in canonical form.

say Net::IPAM::Block->new('fe80::aa/10')->to_string;        # fe80::/10
say Net::IPAM::Block->new('1.2.3.4-1.2.3.36')->to_string;   # 1.2.3.4-1.2.3.36
say Net::IPAM::Block->new('127.0.0.1')->to_string;          # 127.0.0.1/32

Stringification is overloaded with "to_string"

my $b = Net::IPAM::Block->new('fe80::/10');
say $b;                                      # fe80::/10

TO_JSON

helper method for JSON serialization, just calls $block->to_string. See also "OBJECT SERIALISATION" in JSON.

is_cidr

$b->is_cidr

Returns true if the block is a CIDR.

Net::IPAM::Block->new('fe80::aa/10')->is_cidr        # true
Net::IPAM::Block->new('1.2.3.1-1.2.3.2')->is_cidr    # false

cidrsplit

@cidrs = $b->cidrsplit

Returns the next 2 cidrs splitted from block.

Net::IPAM::Block->new('0.0.0.0/7')->cidrsplit    # 0.0.0.0/8  1.0.0.0/8
Net::IPAM::Block->new('fe80::/12')->cidrsplit    # fe80::/13  fe88::/13

Returns undef if cidr mask is at maximum or if block is no CIDR.

to_cidrs

@cidrs = $b->to_cidrs

Returns a list of Net::IPAM::Block objects as true CIDRs, representing the range.

Net::IPAM::Block->new('17.0.0.1-17.0.0.2')->to_cidrs  # 17.0.0.1/32 17.0.0.2/32
Net::IPAM::Block->new('fe80::aa-fe80::ac')->to_cidrs  # fe80::aa/127 fe80::ac/128
Net::IPAM::Block->new('1.2.3.0-1.2.3.101')->to_cidrs  # 1.2.3.0/26 1.2.3.64/27 1.2.3.96/30 1.2.3.100/31

If the range is a CIDR, just returns the CIDR:

Net::IPAM::Block->new('10.0.0.0/8')->to_cidrs         # 10.0.0.0/8
Net::IPAM::Block->new('::1')->to_cidrs                # ::1/128

base

$ip = $b->base

Returns the base IP, as Net::IPAM::IP object.

$b = Net::IPAM::Block->new('fe80::ffff/10');
say $b->base;  # fe80::/10

last

$ip = $b->last

Returns the last IP, as Net::IPAM::IP object.

$b = Net::IPAM::Block->new('10.0.0.0/30')
say $b->last;  # 10.0.0.3

mask

$ip = $b->mask

Returns the netmask as Net::IPAM::IP object.

$b = Net::IPAM::Block->new('10.0.0.0/24')
say $b->mask if defined $b->mask;  # 255.255.255.0

The mask is only defined for real CIDR blocks.

Example:

1.2.3.4            => mask is /32  = 255.255.255.255
::1                => mask is /128 = ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff

10.0.0.0-10.0.0.15 => mask is /28  = 255.255.255.240
::-::f             => mask is /124 = ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0

10.0.0.0/24        => mask is /24  = 255.255.255.0
fe80::/10          => mask is /10  = ffc0:0000:0000:0000:0000:0000:0000:0000

10.0.0.0-10.0.0.13 => mask is undef
::-::5             => mask is undef

hostmask

$ip = $b->hostmask

Returns the hostmask as Net::IPAM::IP object.

$b = Net::IPAM::Block->new('10.0.0.0/24')
say $b->mask;      # 255.255.255.0
say $b->hostmask;  # 0.0.0.255

$b = Net::IPAM::Block->new('fe80::/10')
say $b->mask;      # ffc0::
say $b->hostmask;  #   3f:ffff:ffff:ffff:ffff:ffff:ffff:ffff

The hostmask is only defined for real CIDR blocks.

bitlen

bitlen returns the minimum number of bits to represent a range from base to last

$n = $b->bitlen

obvious for CIDR blocks:

$b = Net::IPAM::Block->new('10.0.0.0/24')
say $b->bitlen;     # 32 - 24 = 8 bit

$b = Net::IPAM::Block->new('::/0');
say $b->bitlen;     # 128 - 0 = 128 bit

not so obvious for ranges:

$b = Net::IPAM::Block->new('2001:db8::affe-2001:db8::cafe');
say $b->bitlen;     # 15 bit (at least)

iter

iter returns the next IP in block, starting with base and stopping at last. Returns undef after last.

$b = Net::IPAM::Block->new('2001:db8::affe-2001:db8::cafe');
while ( my $ip = $b->iter ) {
  say $ip;
}

OUTPUT:

2001:db8::affe
2001:db8::afff
2001:db8::b000
2001:db8::b001
...
2001:db8::cafb
2001:db8::cafc
2001:db8::cafd
2001:db8::cafe

cmp

$a->cmp($b)

Compares two IP blocks:

print $this->cmp($other);
@sorted_blocks = sort { $a->cmp($b) } @unsorted_blocks;

cmp() returns -1, 0, +1:

 0 if $a == $b,

-1 if $a is v4 and $b is v6
+1 if $a is v6 and $b is v4

-1 if $a->base < $b->base
+1 if $a->base > $b->base

-1 if $a->base == $b->base and $a->last > $b->last # $a is super-set of $b
+1 if $a->base == $b->base and $a->last < $b->last # $a is sub-set of $b

is_disjunct_with

$a->is_disjunct_with($b)

Returns true if the blocks are disjunct

a       |----------|
b |---|

a |------|
b          |---|

print "a and b are disjunct" if $a->is_disjunct_with($b)

overlaps_with

$a->overlaps_with($b)

Returns true if the blocks overlap.

a    |-------|
b |------|

a |------|
b    |-------|

a |----|
b      |---------|

a      |---------|
b |----|

contains

$a->contains($b)

Returns true if block a contains block b. a and b may NOT coincide.

if ( $a->contains($b) ) {
  print "block a contains block b\n";
}

a |-----------------| |-----------------| |-----------------|
b   |------------|    |------------|           |------------|

The argument may also be a Net::IPAM::IP address object.

if ( $a->contains($ip) ) {
  print "block a contains ip\n";
}

diff

@diff = $outer->diff(@inner)

Returns all blocks in outer block, minus the inner blocks.

my $outer = Net::IPAM::Block->new("192.168.2.0/24");
my @inner = (
  Net::IPAM::Block->new("192.168.2.0/26"),
  Net::IPAM::Block->new("192.168.2.240-192.168.2.249"),
);

my @diff = $outer->diff(@inner);

# diff: [192.168.2.64-192.168.2.239, 192.168.2.250-192.168.2.255]

FUNCTIONS

sort_block

use Net::IPAM::Block 'sort_block';

@sorted_blocks = sort_block @unsorted_blocks;

Faster sort implemention (Schwartzian transform) as explcit sort function:

@sorted_blocks = sort { $a->cmp($b) } @unsorted_blocks;

merge

use Net::IPAM::Block 'merge';

@merged = merge(@blocks)

Returns the minimal number of blocks spanning the range of input blocks.

If CIDRs are required, use the following idiom:

@cidrs = map { $_->to_cidrs } merge(@blocks);

aggregate

*** DEPRECATED *** use merge in favor of

OPERATORS

Net::IPAM::Block overloads the following operators.

bool

my $bool = !!$block;

Always true.

stringify

my $str = "$block";

Alias for "to_string".

AUTHOR

Karl Gaissmaier, <karl.gaissmaier(at)uni-ulm.de>

BUGS

Please report any bugs or feature requests to bug-net-ipam-block at rt.cpan.org, or through the web interface at https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-IPAM-Block. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.

SUPPORT

You can find documentation for this module with the perldoc command.

perldoc Net::IPAM::Block

You can also look for information at:

  • on github

    TODO

SEE ALSO

Net::IPAM::IP Net::IPAM::Tree

LICENSE AND COPYRIGHT

This software is copyright (c) 2020-2021 by Karl Gaissmaier.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.