# Use of the Net-Silk library and related source code is subject to the
# terms of the following licenses:
# 
# GNU Public License (GPL) Rights pursuant to Version 2, June 1991
# Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013
# 
# NO WARRANTY
# 
# ANY INFORMATION, MATERIALS, SERVICES, INTELLECTUAL PROPERTY OR OTHER 
# PROPERTY OR RIGHTS GRANTED OR PROVIDED BY CARNEGIE MELLON UNIVERSITY 
# PURSUANT TO THIS LICENSE (HEREINAFTER THE "DELIVERABLES") ARE ON AN 
# "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY 
# KIND, EITHER EXPRESS OR IMPLIED AS TO ANY MATTER INCLUDING, BUT NOT 
# LIMITED TO, WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE, 
# MERCHANTABILITY, INFORMATIONAL CONTENT, NONINFRINGEMENT, OR ERROR-FREE 
# OPERATION. CARNEGIE MELLON UNIVERSITY SHALL NOT BE LIABLE FOR INDIRECT, 
# SPECIAL OR CONSEQUENTIAL DAMAGES, SUCH AS LOSS OF PROFITS OR INABILITY 
# TO USE SAID INTELLECTUAL PROPERTY, UNDER THIS LICENSE, REGARDLESS OF 
# WHETHER SUCH PARTY WAS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. 
# LICENSEE AGREES THAT IT WILL NOT MAKE ANY WARRANTY ON BEHALF OF 
# CARNEGIE MELLON UNIVERSITY, EXPRESS OR IMPLIED, TO ANY PERSON 
# CONCERNING THE APPLICATION OF OR THE RESULTS TO BE OBTAINED WITH THE 
# DELIVERABLES UNDER THIS LICENSE.
# 
# Licensee hereby agrees to defend, indemnify, and hold harmless Carnegie 
# Mellon University, its trustees, officers, employees, and agents from 
# all claims or demands made against them (and any related losses, 
# expenses, or attorney's fees) arising out of, or relating to Licensee's 
# and/or its sub licensees' negligent use or willful misuse of or 
# negligent conduct or willful misconduct regarding the Software, 
# facilities, or other rights or assistance granted by Carnegie Mellon 
# University under this License, including, but not limited to, any 
# claims of product liability, personal injury, death, damage to 
# property, or violation of any laws or regulations.
# 
# Carnegie Mellon University Software Engineering Institute authored 
# documents are sponsored by the U.S. Department of Defense under 
# Contract FA8721-05-C-0003. Carnegie Mellon University retains 
# copyrights in all material produced under this contract. The U.S. 
# Government retains a non-exclusive, royalty-free license to publish or 
# reproduce these documents, or allow others to do so, for U.S. 
# Government purposes only pursuant to the copyright license under the 
# contract clause at 252.227.7013.

package Net::Silk::IPAddr;

use strict;
use warnings;
use Carp;

use Net::Silk qw( :basic );

use constant _bool => 1;

use overload (
  '""'   => \&str,
  '0+'   => \&num,
  '&'    => \&mask,
  '<=>'  => \&_cmp,
  '>'    => \&_gt,
  '<'    => \&_lt,
  '>='   => \&_ge,
  '<='   => \&_le,
  '=='   => \&_eq,
  '!='   => \&_ne,
  'cmp'  => \&_cmp,
  'gt'   => \&_gt,
  'lt'   => \&_lt,
  'ge'   => \&_ge,
  'le'   => \&_le,
  'eq'   => \&_eq,
  'ne'   => \&_ne,
  'bool' => \&_bool,
  '='    => \&_clone,
);

sub as_ipv4 {
  my $ip;
  eval { $ip = shift->_as_ipv4 };
  $@ ? () : $ip;
}

sub as_ipv6 { shift->_as_ipv6 }

sub mask { Net::Silk::IPAddr::_mask($_[0], hex_cast($_[1])) }

sub _clone { $_[0]->new($_[0]) }

sub _cmp { Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) }

sub _gt { Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) >  0 }
sub _ge { Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) >= 0 }
sub _lt { Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) <  0 }
sub _le { Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) <= 0 }

sub _eq  { defined $_[1] &&
           Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) == 0 }

sub _ne  { (! defined $_[1]) ||
           Net::Silk::IPAddr::_xscmp($_[0], hex_cast($_[1])) != 0 }

###

package Net::Silk::IPv4Addr;

use strict;
use warnings;

use base qw( Net::Silk::IPAddr );

use Net::Silk qw( :basic );

use constant is_ipv6 => 0;

###

package Net::Silk::IPv6Addr;

use strict;
use warnings;

use base qw( Net::Silk::IPAddr );

use Net::Silk qw( :basic );

use Math::Int128 qw( net_to_uint128 );

use constant is_ipv6 => 1;

use overload (
  '0+'  => \&num,
  '<=>' => \&_cmp,
  '>'   => \&_gt,
  '<'   => \&_lt,
  '>='  => \&_ge,
  '<='  => \&_le,
  '=='  => \&_eq,
  '!='  => \&_ne,
  'cmp' => \&_cmp,
  'gt'  => \&_gt,
  'lt'  => \&_lt,
  'ge'  => \&_ge,
  'le'  => \&_le,
  'eq'  => \&_eq,
  'ne'  => \&_ne,
  '='   => \&_clone,
);

sub _cmp { Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) }

sub _gt { Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) >  0 }
sub _ge { Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) >= 0 }
sub _lt { Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) <  0 }
sub _le { Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) <= 0 }

sub _eq  {
  defined $_[1] &&
           Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) == 0 }

sub _ne  { (! defined $_[1]) ||
           Net::Silk::IPv6Addr::_xscmp($_[0], hex_cast($_[1])) != 0 }

sub num { net_to_uint128(Net::Silk::IPAddr::num($_[0])) }

###

1;

__END__

=head1 NAME

Net::Silk::IPAddr - SiLK IP addresses

=head1 SYNOPSIS

  use Net::Silk::IPAddr;

  my $ipv4 = Net::Silk::IPAddr->new("1.2.3.4");
  my $ipv6 = Net::Silk::IPAddr->new("::ffff:1.2.3.4");

  $ipv4->is_ipv6; # false
  $ipv6->is_ipv6; # true

  $ipv4 = Net::Silk::IPv4Addr->new("::ffff:1.2.3.4");
  $ipv6 = Net::Silk::IPv6Addr->new("1.2.3.4");

  $ipv4->is_ipv6; # false
  $ipv6->is_ipv6; # true

  my $ip = $ipv4->mask('255.255.255.0');

=head1 DESCRIPTION

C<Net::Silk::IPAddr> represents an IPv4 or IPv6 address. These
manifest as the subclasses C<Net::Silk::IPv4Addr> and
C<Net::Silk::IPv6Addr>, respectively.

=head1 METHODS

=over

=item new($spec)

Returns an IP address object. The given spec can be a string
representation of the address or another IP address object.
Returns either a C<Net::Silk::IPv4Addr> or a C<Net::Silk::IPv6Addr>
if the string appears to be an IPv6 address and SILK_IPV6_ENABLED
is true.

=item str()

Returns the string representation of this IP address. This
method is tied to the C<""> operator.

=item padded()

Returns the zero-padded string representation of this IP address.

=item octets()

Returns a list of octets representing this IP address.

=item num()

Returns the integer representation of this IP address.

=item is_ipv6()

Returns true if this is a C<Net::Silk::IPv6Addr>.

=item as_ipv4()

Return a C<Net::Silk::IPv4Addr> representation of this
address if possible.

=item as_ipv6()

Return a C<Net::Silk::IPv6Addr> representation of this address.

=item mask($mask)

Return a copy of this address masked by the provided IP address mask.

=item country_code()

Return the two character country code associated with this address
if available.

=back

=head2 IPv4 METHODS

=over

=item from_int()

Return an IPv4 address from the given integer. Also accepts
hex string representations, e.g. "0xffffffff"

=item mask_prefix()

Return a copy of this address masked by the CIDR prefix bits.
All bits below the I<prefix>th bit will be set to zero. The
maximum value for prefix is 32 for IPv4.

=back

=head2 IPv6 METHODS

=over

=item from_int()

Return an IPv6 address from the given integer. Also accepts a
hex string representation, e.g. "0xffff01020304"

=item mask_prefix()

Return a copy of this address masked by the given CIDR prefix
bits. All bits below the I<prefix>th bit will be set to zero.
The maximum value for prefix is 128 for IPv6.

=back

=head1 OPERATORS

The following operators are overloaded and work with
C<Net::Silk::IPAddr> objects:

  ""              cmp
  0+              gt
  &               lt
  <=>             ge
  >               le
  <               eq
  >=              ne
  <=              bool
  ==              =
  !=

=head1 SEE ALSO

L<Net::Silk>, L<Net::Silk::RWRec>, L<Net::Silk::IPSet>, L<Net::Silk::IPWildcard>, L<Net::Silk::Bag>, L<Net::Silk::Pmap>, L<Net::Silk::TCPFlags>, L<Net::Silk::ProtoPort>, L<Net::Silk::File>, L<Net::Silk::Site>, L<silk(7)>

=head1 COPYRIGHT & LICENSE

Copyright (C) 2011-2015 by Carnegie Mellon University

Use of the Net-Silk library and related source code is subject to the
terms of the following licenses:

GNU Public License (GPL) Rights pursuant to Version 2, June 1991
Government Purpose License Rights (GPLR) pursuant to DFARS 252.227.7013

NO WARRANTY

See GPL.txt and LICENSE.txt for more details.

=cut
