Coder Social home page Coder Social logo

raku-ip-addr's Introduction

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 by ip 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 in IP::Addr::Common. Currently the following scopes are known:

      • undetermined

      • mpublic

      • software

      • private

      • host

      • subnet

      • documentation

      • internet

      • routing

      • link

      Of those routing and link 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!

SEE ALSO

ChangeLog

AUTHOR

Vadim Belman [email protected]

raku-ip-addr's People

Contributors

vrurg avatar

Stargazers

Tim Howe avatar Dan White avatar  avatar

Watchers

James Cloos avatar  avatar  avatar

raku-ip-addr's Issues

Wrong results with `no precompilation;`

The module does seems only to work correct, if the code was precompiled.
Normal behavior as expected:

raku -v
This is Rakudo version 2019.11 built on MoarVM version 2019.11
implementing Perl 6.d.

RAKUDOLIB=./lib/ raku -MIP::Addr -e 'IP::Addr.new("1.1.1.1").say'
#1.1.1.1

To disable precompilation I've added no precompilation; in the Handler.pm6:

#! /usr/bin/env false

use v6.c;
no precompilation;

Then the module does return 0.0.0.0 instead of 1.1.1.1 and multiple warnings are shown on the console:

RAKUDOLIB=./lib/ raku -MIP::Addr -e 'IP::Addr.new("1.1.1.1").say'
Use of uninitialized value of type Any in numeric context
  in method bitcap at -e line 106
Use of uninitialized value of type Any in numeric context
  in method bitcap at -e line 106
Use of uninitialized value of type Any in numeric context
  in method bits2mask at -e line 322
...
Use of uninitialized value of type Any in numeric context
  in method bitcap at -e line 106
0.0.0.0

It does look like, that the %bitcap-mask Hash only can be read correctly when precompiled before. If I change the %bitcap-mask to an our variable, the code does work also without precompilation:

our %bitcap-mask = (0..128).map: { $_ => 2**$_ - 1 }; # Mask for each bit capacity

It does also work, if I place the %bitcap-mask after the unit role initialisation

#my %bitcap-mask = (0..128).map: { $_ => 2**$_ - 1 }; # Mask for each bit capacity

unit role IP::Addr::Handler;
my %bitcap-mask = (0..128).map: { $_ => 2**$_ - 1 }; # Mask for each bit capacity

I would have expected, that the precompilation does only affect startup speed, but not the behavior of the code.

Error in Range to CIDR support

Hi,
Thanks for this module, Im trying to convert IP range to CIDR but it seems the module is not behaving correctly:

[1] > say IP::Addr.new( "192.1.1.3/24" ).network;
192.1.1.0/24
[1] > say IP::Addr.new( "192.168.1.1-192.168.1.255" ).network;
192.1.1.1/0

I've tried with any ranges the prefix is always /0 , can you have a look to fix it ?

Fails to install on FBSD

FreeBSD yep.myhome 13.0-RELEASE-p3 FreeBSD 13.0-RELEASE-p3 #0: Tue Jun 29 19:46:20 UTC 2021 [email protected]:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64

zef install IP::Addr

===> Searching for: IP::Addr
===> Updating fez mirror: http://360.zef.pm/
===> Updating cpan mirror: https://raw.githubusercontent.com/ugexe/Perl6-ecosystems/master/cpan1.json
===> Updating p6c mirror: https://raw.githubusercontent.com/ugexe/Perl6-ecosystems/master/p6c1.json
===> Updated p6c mirror: https://raw.githubusercontent.com/ugexe/Perl6-ecosystems/master/p6c1.json
===> Updated fez mirror: http://360.zef.pm/
===> Updated cpan mirror: https://raw.githubusercontent.com/ugexe/Perl6-ecosystems/master/cpan1.json
===> Searching for missing dependencies: Test::When, p6doc, Pod::To::Markdown
===> Searching for missing dependencies: Pod::To::HTML:authgithub:Raku, Doc::TypeGraph, Pod::To::HTML, Pod::To::BigPage
===> Searching for missing dependencies: HTTP::UserAgent, IO::Socket::SSL, Template::Mustache, Pod::Load:ver<0.4.0+>, OO::Monitors, Test::Output, dot:from
===> Failed to find dependencies: dot:from
Failed to resolve some missing dependencies (use e.g. --exclude="dot" to skip)
root@nas:~/lucera-vm # zef install IP::Addr
===> Searching for: IP::Addr
===> Searching for missing dependencies: Test::When, p6doc, Pod::To::Markdown
===> Searching for missing dependencies: Pod::To::HTML:authgithub:Raku, Doc::TypeGraph, Pod::To::HTML, Pod::To::BigPage
===> Searching for missing dependencies: HTTP::UserAgent, IO::Socket::SSL, Template::Mustache, Pod::Load:ver<0.4.0+>, OO::Monitors, Test::Output, dot:from
===> Failed to find dependencies: dot:from
Failed to resolve some missing dependencies (use e.g. --exclude="dot" to skip)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.