NAME
IP::Addr - dealing with IPv4/IPv6 addresses
SYNOPSIS
my $cidr = IP::Addr.new( "192.0.2.2/27" );
say $cidr;
say $cidr.ip;
for $cidr.network.each -> $ip {
say $ip;
}
my $cidr6 = IP::Addr.new( "600d::f00d/123" );
say $cidr6;
say $cidr6.ip;
DESCRIPTION
This module provides functionality for working with IPv4/IPv6 addresses.
Module Structure
The main interface is provided by IP::Addr
class. Typical class usage is demonstrated in the synopsis. The class is a frontend which tries to determine version of the IP address provided to its constructor and creates corresponding handler object available on its handler
attribute. All methods of the handler are available on IP::Addr
object via handles
trait.
For example, for an arbitrary $ip
object of the class $ip.ip
call is actually same as calling $ip.handler.ip
. Method ip
is a universal one for both v4 and v6 addresses and therefore it is not necessary to care about what exact kind of object we're currently dealing with.
Similarly, version-dependant methods are available too but only when corresponding handler is active. For example:
say IP::Addr.new( "192.0.2.2/27" ).broadcast;
is a valid call; while
say IP::Addr.new( "2001:db8::/123" ).broadcast;
will fail with "no method" exception because broadcast
is not available for IPv6 addresses.
Glossary
Address forms
Besides of its version each IP address has one more characteristic property: form. It is defined by handler's attribute of the same name: $!form
. Particular forms are defined by IP-FORM enum defined in IP::Addr::Common
:
ip
Simple IP address. It has prefix length of 32 bits.
cidr
CIDR form is an IP address with prefix defined.
192.0.2.3/24 192.0.2.3/255.255.255.0 2001::/64
range
A range is defined by its first and last IP addresses. It has a selected or current IP address which could be changed as a result of increase, decrease, or iteration operations.
192.0.2.3-192.0.2.20 2001::1-2001::1f
Ranged forms
CIDR and ranges are ranged forms contrary to a single IP form.
N-tets
As it is known IP addresses are represented by groups of integers called octets for IPv4 and hextets for IPv6 (there are variations but I chose these two). N-tets is used as a general term for both of them.
METHODS
Constructor
Class constructor new
simply re-dispatches its arguments to method set
.
set
$ip.set( Str $source )
/$ip.set( Str :$source! )
$source
is a string representation of an IP address in either plain or CIDR notation, or of a range of addresses in a form *- *. Formats of valid IP addresses are defined by corresponding standards.$ip.set( [ :v4 | :v6 ], *%params )
Creates a handler object of specified version of handler (v4 or v6) by passing named
%params
to its constructor.For example, the following statement:
$ip.set( :v4, ip => 3221225986, prefix-len => 24 )
Is equivalent to:
$ip.set( "192.0.2.2/24" )
Note: all calls to
set
method result in creation of a new handler object. I.e.:my $old-handler = $ip.handler; $ip.set( ... ); say $old-handler === $ip.handler; # False
Str
Returns a valid string representation of the IP object.
gist
Same as Str
method.
each
Returns an iterable object which would iterate over IPs contained in the current object starting with selected address (i.e. the one returned by ip
method). For ranged forms to iterate over the whole range (from the first-ip
to the last-ip
) use of method first
is recommended:
.say for IP::Addr.new( "192.0.2.3/29" ).each; # 192.0.2.3/29\n192.0.2.4/29 ...
.say for IP::Addr.new( "192.0.2.3/29" ).first.each; # 192.0.2.0/29\n192.0.2.1/29 ...
Supply
Similar to each
method but returns a Supply
object. Same rule about starting with selected IP and use of first
method apply.
HANDLER METHODS
This sections documents methods common for both IPv4 and IPv6 handlers.
Notes
For all methods accepting another IP address as a parameter and where descriptions has a statement "same version only" X::IPAddr::TypeCheck
exception would be thrown if object with a handler of different version is passed.
Address method parameters could either be IP::Addr
instances or string representations.
set
Configures the handler object.
Note In the following subsection $handler
notation is used instead of $ip.handler
.
$handler.set( Str:D $source )
/$handler.set( Str:D :$source! )
Handler attributes are set by parsing a string representation of IP address.
$handler.set( Int:D :$ip!, Int:D :$!prefix-len )
Configures handler object as CIDR form.
$handler.set( Int:D :$first!, Int:D :$!last, Int :$ip? )
Configures handler object as range form. Optional named parameter
:ip
defines selected IP within range (i.e. the one returned byip
method). If omitted then range initial selected IP is its first address.$handler.set( Int:D $ip! )
Configures a single IP form.
$handler.set( Int:D @n-tets )
Configures a single IP form from integer octets for IPv4 or hextets for IPv6. Number of elements in @n-tets array is defined by the method of the same name.
addr-len
Returns number of bits for correponding IP version (32 for IPv4 and 128 for IPv6).
n-tets
Returns number of n-tets for the current handler (4 for IPv4 and 8 for IPv6).
version
Returns integer version of the IP object (4 or 6).
ip-classes
Returns list of hashes of reserved IP ranges. Each hash has two keys:
net
IP::Addr
object representing the reserved range.info
Another hash containing information about the scope of the reserved range in very brief text description:
scope
Scopes are defined by
SCOPE
enum inIP::Addr::Common
. Currently the following scopes are known:undetermined
mpublic
software
private
host
subnet
documentation
internet
routing
link
Of those
routing
andlink
are specific to IPv6.public
isn't officially recognized but used to represent anything not been reserved.undetermined
is also a special value to be returned if a requested range of IP addresses overlaps with a reserved range but isn't fully contained in it.description
Textual information about the reserved block.
ip
Returns a new IP::Addr
object representing just an IP address of the current IP::Addr
object.
my $ip = IP::Addr.new( "192.0.2.3/24" );
say $ip; # 192.0.2.3/24
say $ip.ip; # 192.0.2.3
say $ip.ip.WHO; # IP::Addr
prefix
Returns CIDR representation of any form of IP address. For example:
say IP::Addr.new( "192.0.2.3" ).prefix; # 192.0.2.3/32
For IPv4 handler additional named parameter :mask
can be used to use network mask instead of prefix length:
say IP::Addr.new( "192.0.2.3/24" ).prefix( :mask ); # 192.0.2.3/255.255.255.0
first-ip
IP::Addr
object for the first IP address in the range. For single IP will be the same as ip
method.
last-ip
IP::Addr
object for the last IP address in the range. For single IP will be the same as ip
method.
network
IP::Addr
object of the network current IP object belongs to. Makes real sense for CIDR form only though can be used with any other form too.
mask
Returns string representation of the current IP object mask. Doesn't make much sense for IPv6 addresses because there is officially no such thing for them.
wildcard
Returns string representation of current IP object wildcard. Doesn't make much sense for IPv6 addresses because there is officially no such thing for them.
size
Returns number of IP addresses contained in the current IP::Addr
object. For example:
say IP::Addr.new( "192.0.0.0/13" ).size; # 524288
say IP::Addr.new( "192.0.2.3-192.0.2.23" ); # 21
int-ip
Returns integer value of the IP address.
int-first-ip
Returns integer value of the first IP address in the current IP object.
int-last-ip
Returns integer value of the last IP address in the current IP object.
int-mask
Returns integer value of current IP object mask. Though not defined as such for IPv6 addresses but could be useful in some address arithmetics.
int-wildcard
Returns integer value of current IP object wildcard. Though not defined as such for IPv6 addresses but could be useful in some address arithmetics.
inc
/ succ
Increments IP address by 1. For ranged IP forms result of this operation won't be greater than the last IP of the range:
my $ip = IP::Addr.new( "192.0.2.255/24" );
say $ip.inc; # 192.0.2.255/24
Rerturns current IP::Addr
object.
dec
/ pred
Decrements IP address by 1. For ranged IP forms result of this operation won't be less than the first IP of the range:
my $ip = IP::Addr.new( "192.0.2.0/24" );
say $ip.dec; # 192.0.2.0/24
Returns current IP::Addr
object.
add( Int:D $count )
Shifts IP of the current object by $count
positions higher. $count
could be negative. For ranged IP form the result of the operation won't leave the range boundaries:
my $ip = IP::Addr.new( "192.0.2.255/24" );
say $ip.add( 10 ); # 192.0.2.255/24
say $ip.add( -300 ); # 192.0.2.0/24
Returns current IP::Addr
object.
eq( $addr )
Same version only.
Returns True if current object is equal to $addr
.
lt( $addr )
Same version only.
Returns true if the current object is less than $addr
.
gt( $addr )
Same version only.
Returns true if the current object is greater than $addr
cmp( $addr )
Same version only.
Returns one of three Order
values: Less
, Same
, or More
. For ranges comparison is performed by the selected IP.
contains( $addr )
Same version only.
Returns True if current object contains $addr
. Wether the $addr
object is the same (e.g. eq
method would return True) then it is also considered as contained.
overlaps( $addr )
Same version only.
Returns True if the current object and $addr
have at least one common IP address. Useful for starting iteration:
first
Returns a new IP::Addr
object whose IP address is the first IP of the current object. Useful for starting iteration.
my $ip = IP::Addr.new( "192.0.2.12/24" );
for $ip.first.each { say $_ } # 192.0.2.0\n192.0.2.1\n...
See each
method.
next
Returns a new IP::Addr
object successive to the current object or Nil if current is the last IP of the range.
prev
Returns a new IP::Addr
object preceding the current object or Nil if current is the first IP of the range.
next-network
Returns a new IP::Addr
object containing network successive to the network of the current object. Valid for CIDR form only. Flips over begining/end of IP range:
$ip = IP::Addr.new( "255.255.255.13/24" );
say $ip.next-network; # 0.0.0.0/24
prev-network
Returns a new IP::Addr
object containing network preceding the network of the current object. Valid for CIDR form only. Flips over the begining of IP range:
$ip = IP::Addr.new( "0.0.0.2/24" );
say $ip.prev-network; # 255.255.255.0/24
next-range
Returns a new IP::Addr
object containing range of the same length successive to the current object. Valid for range form only.
prev-range
Returns a new IP::Addr
object containing range of the same length preceding the current object. Valid for range form only.
to-int( @n-tets )
Converts an array of n-tets to integer value corresponding to the current handler's IP version.
to-n-tets( Int:D $addr )
Splits integer represnation of IP address into n-tets corresponding to the current handler's IP version.
info
Returns a hash with information about the current IP object. The hash contains two keys: scope
and description
. See ip-classes
method for more information.
Str
Stringifies current IP object with regard to its form.
OPERATORS
For all supported operators where both operands are addresses at least one of them has to be a IP::Addr
object. The other one could be a string representation of an address.
prefix/postfix ++
and prefix/postfix --
Standard Raku operatios working by calling succ
/pred
methods on IP::Addr
object.
infix + ( $addr, $int )
Adds an integer value to the address. The resulting address will never get out of network/range boundaries for objects of corresponding forms. A new IP::Addr
object is returned.
$ip2 = $ip1 + 3;
infix - ( $addr, $int )
Deducts an integer value from the address. The resulting address will never get out of network/range boundaries for objects of corresponding forms. A new IP::Addr
object is returned.
$ip2 = $ip1 - 3;
infix cmp ( $addr1, $addr2 )
Compares two IP addresses.
given $ip1 cmp $ip2 {
when Less { say "smaller" }
when Same { say "same" }
when More { say "bigger" }
}
infix eqv / infix == ( $addr1, $addr2 )
Checks if two addresses are equal. See handler's eq
method.
infix < ( $addr1, $addr2 )
True if $addr1
is less than $addr2
. See handler's lt
method.
infix <= / infix ≤ ( $addr1, $addr2 )
True if $addr1
is less than or equal to $addr2
.
infix > ( $addr1, $addr2 )
True if $addr1
is greater than $addr2
. See handler's gt
method.
infix >= / infix ≥ ( $addr1, $addr2 )
True $addr1
greater than or equal to $addr2
.
infix (cont) / infix ⊇ ( $addr1, $addr2 )
True if $addr1
object contains $addr2
. See handler's contains
method.
infix ⊆ ( $addr1, $addr2 )
True if $addr1
is contained by $addr2
.
CAVEATS
The author doesn't use IPv6 in his setups. All the functionality provided here is developed using information from corresponding Wikipedia pages. Therefore, "here be dragons"©. Please, report back any issue encountered!
AUTHOR
Vadim Belman vrurg@cpan.org