Net::CIDR.3pm

Langue: en

Version: 2010-06-27 (fedora - 01/12/10)

Section: 3 (Bibliothèques de fonctions)

NAME

Net::CIDR - Manipulate IPv4/IPv6 netblocks in CIDR notation

SYNOPSIS

     use Net::CIDR;
 
     use Net::CIDR ':all';
 
     print join("\n",
           Net::CIDR::range2cidr("192.68.0.0-192.68.255.255",
                                 "10.0.0.0-10.3.255.255"))
                . "\n";
     #
     # Output from above:
     #
     # 192.68.0.0/16
     # 10.0.0.0/14
 
     print join("\n",
           Net::CIDR::range2cidr(
                 "dead:beef::-dead:beef:ffff:ffff:ffff:ffff:ffff:ffff"))
                . "\n";
 
     #
     # Output from above:
     #
     # dead:beef::/32
 
     print join("\n",
              Net::CIDR::range2cidr("192.68.1.0-192.68.2.255"))
                   . "\n";
     #
     # Output from above:
     #
     # 192.68.1.0/24
     # 192.68.2.0/24
 
     print join("\n", Net::CIDR::cidr2range("192.68.0.0/16")) . "\n";
     #
     # Output from above:
     #
     # 192.68.0.0-192.68.255.255
 
     print join("\n", Net::CIDR::cidr2range("dead::beef::/46")) . "\n";
     #
     # Output from above:
     #
     # dead:beef::-dead:beef:3:ffff:ffff:ffff:ffff:ffff
 
     @list=("192.68.0.0/24");
     @list=Net::CIDR::cidradd("192.68.1.0-192.68.1.255", @list);
 
     print join("\n", @list) . "\n";
     #
     # Output from above:
     #
     # 192.68.0.0/23
 
     print join("\n", Net::CIDR::cidr2octets("192.68.0.0/22")) . "\n";
     #
     # Output from above:
     #
     # 192.68.0
     # 192.68.1
     # 192.68.2
     # 192.68.3
 
     print join("\n", Net::CIDR::cidr2octets("dead::beef::/46")) . "\n";
     #
     # Output from above:
     #
     # dead:beef:0000
     # dead:beef:0001
     # dead:beef:0002
     # dead:beef:0003
 
     @list=("192.68.0.0/24");
     print Net::CIDR::cidrlookup("192.68.0.12", @list);
     #
     # Output from above:
     #
     # 1
 
     @list = Net::CIDR::addr2cidr("192.68.0.31");
     print join("\n", @list);
     #
     # Output from above:
     #
     # 192.68.0.31/32
     # 192.68.0.30/31
     # 192.68.0.28/30
     # 192.68.0.24/29
     # 192.68.0.16/28
     # 192.68.0.0/27
     # 192.68.0.0/26
     # 192.68.0.0/25
     # 192.68.0.0/24
     # 192.68.0.0/23
     # [and so on]
 
     print Net::CIDR::addrandmask2cidr("195.149.50.61", "255.255.255.248")."\n";
     #
     # Output from above:
     #
     # 195.149.50.56/29
 
 

DESCRIPTION

The Net::CIDR package contains functions that manipulate lists of IP netblocks expressed in CIDR notation. The Net::CIDR functions handle both IPv4 and IPv6 addresses.

@cidr_list=Net::CIDR::range2cidr(@range_list);

Each element in the @range_list is a string ``start-finish'', where ``start'' is the first IP address and ``finish'' is the last IP address. range2cidr() converts each range into an equivalent CIDR netblock. It returns a list of netblocks except in the case where it is given only one parameter and is called in scalar context.

For example:

     @a=Net::CIDR::range2cidr("192.68.0.0-192.68.255.255");
 
 

The result is a one-element array, with $a[0] being ``192.68.0.0/16''. range2cidr() processes each ``start-finish'' element in @range_list separately. But if invoked like so:

     $a=Net::CIDR::range2cidr("192.68.0.0-192.68.255.255");
 
 

The result is a scalar ``192.68.0.0/16''.

Where each element cannot be expressed as a single CIDR netblock range2cidr() will generate as many CIDR netblocks as are necessary to cover the full range of IP addresses. Example:

     @a=Net::CIDR::range2cidr("192.68.1.0-192.68.2.255");
 
 

The result is a two element array: (``192.68.1.0/24'',``192.68.2.0/24'');

     @a=Net::CIDR::range2cidr(
                    "d08c:43::-d08c:43:ffff:ffff:ffff:ffff:ffff:ffff");
 
 

The result is an one element array: (``d08c:43::/32'') that reflects this IPv6 netblock in CIDR notation.

range2cidr() does not merge adjacent or overlapping netblocks in @range_list.

@range_list=Net::CIDR::cidr2range(@cidr_list);

The cidr2range() functions converts a netblock list in CIDR notation to a list of ``start-finish'' IP address ranges:
     @a=Net::CIDR::cidr2range("10.0.0.0/14", "192.68.0.0/24");
 
 

The result is a two-element array: (``10.0.0.0-10.3.255.255'', ``192.68.0.0-192.68.0.255'').

     @a=Net::CIDR::cidr2range("d08c:43::/32");
 
 

The result is a one-element array: (``d08c:43::-d08c:43:ffff:ffff:ffff:ffff:ffff:ffff'').

cidr2range() does not merge adjacent or overlapping netblocks in @cidr_list.

@netblock_list = Net::CIDR::addr2cidr($address);

The addr2cidr function takes an IP address and returns a list of all the CIDR netblocks it might belong to:
     @a=Net::CIDR::addr2cidr('192.68.0.31');
 
 

The result is a thirtythree-element array: ('192.68.0.31/32', '192.68.0.30/31', '192.68.0.28/30', '192.68.0.24/29',
 [and so on]) consisting of all the possible subnets containing this address from 0.0.0.0/0 to address/32.

Any addresses supplied to addr2cidr after the first will be ignored. It works similarly for IPv6 addresses, returning a list of one hundred and twenty nine elements.

$cidr=Net::CIDR::addrandmask2cidr($address, $netmask);

The addrandmask2cidr function takes an IP address and a netmask, and returns the CIDR range whose size fits the netmask and which contains the address. It is an error to supply one parameter in IPv4-ish format and the other in IPv6-ish format, and it is an error to supply a netmask which does not consist solely of 1 bits followed by 0 bits. For example, '255.255.248.192' is an invalid netmask, as is '255.255.255.32' because both contain 0 bits in between 1 bits.

Technically speaking both of those *are* valid netmasks, but a) you'd have to be insane to use them, and b) there's no corresponding CIDR range.

@octet_list=Net::CIDR::cidr2octets(@cidr_list);

cidr2octets() takes @cidr_list and returns a list of leading octets representing those netblocks. Example:
     @octet_list=Net::CIDR::cidr2octets("10.0.0.0/14", "192.68.0.0/24");
 
 

The result is the following five-element array: (``10.0'', ``10.1'', ``10.2'', ``10.3'', ``192.68.0'').

For IPv6 addresses, the hexadecimal words in the resulting list are zero-padded:

     @octet_list=Net::CIDR::cidr2octets("::dead:beef:0:0/110");
 
 

The result is a four-element array: (``0000:0000:0000:0000:dead:beef:0000'', ``0000:0000:0000:0000:dead:beef:0001'', ``0000:0000:0000:0000:dead:beef:0002'', ``0000:0000:0000:0000:dead:beef:0003''). Prefixes of IPv6 CIDR blocks should be even multiples of 16 bits, otherwise they can potentially expand out to a 32,768-element array, each!

@cidr_list=Net::CIDR::cidradd($block, @cidr_list);

The cidradd() functions allows a CIDR list to be built one CIDR netblock at a time, merging adjacent and overlapping ranges. $block is a single netblock, expressed as either ``start-finish'', or ``address/prefix''. Example:
     @cidr_list=Net::CIDR::range2cidr("192.68.0.0-192.68.0.255");
     @cidr_list=Net::CIDR::cidradd("10.0.0.0/8", @cidr_list);
     @cidr_list=Net::CIDR::cidradd("192.68.1.0-192.68.1.255", @cidr_list);
 
 

The result is a two-element array: (``10.0.0.0/8'', ``192.68.0.0/23''). IPv6 addresses are handled in an analogous fashion.

$found=Net::CIDR::cidrlookup($ip, @cidr_list);

Search for $ip in @cidr_list. $ip can be a single IP address, or a netblock in CIDR or start-finish notation. lookup() returns 1 if $ip overlaps any netblock in @cidr_list, 0 if not.

$ip=Net::CIDR::cidrvalidate($ip);

Validate whether $ip is a valid IPv4 or IPv6 address, or a CIDR. Returns its argument or undef. Spaces are removed, and IPv6 hexadecimal address are converted to lowercase.

If $ip contains a ``/'', it must be a valid CIDR, otherwise it must be a valid IPv4 or an IPv6 address.

A technically invalid CIDR, such as ``192.168.0.1/24'' fails validation, returning undef.

BUGS

Garbage in, garbage out. Always use cidrvalidate() before doing anything with untrusted input. Otherwise, ``slightly'' invalid input will work (extraneous whitespace is generally OK), but the functions will croak if you're totally off the wall.

AUTHOR

Sam Varshavchik <sam@email-scan.com>

With some contributions from David Cantrell <david@cantrell.org.uk>