Net-DHCPv6
view release on metacpan or search on metacpan
lib/Net/DHCPv6/Option/AftrName.pm view on Meta::CPAN
#!/bin/false
# ABSTRACT: AFTR Name option (code 88) -- RFC 6334 domain name
# PODNAME: Net::DHCPv6::Option::AftrName
use strictures 2;
package Net::DHCPv6::Option::AftrName;
$Net::DHCPv6::Option::AftrName::VERSION = '0.003';
use Net::DHCPv6::OptionList ();
use Net::DHCPv6::Option ();
use Carp qw( croak );
use Net::DHCPv6::Constants qw(
$DN_COMPRESS_MASK $DN_LABEL_MASK $OPTION_AFTR_NAME
);
use Net::DHCPv6::X::Truncated ();
use Net::DHCPv6::X::BadOption ();
use parent 'Net::DHCPv6::Option';
use namespace::clean;
my $EMPTY = q();
my $MAX_PTR_DEPTH = 255; ## no critic (ValuesAndExpressions::ProhibitMagicNumbers)
sub _encode_domain {
my ( $domain ) = @_;
return chr( 0 ) unless defined $domain && CORE::length( $domain );
my @labels = split m/[.]/, $domain;
return join( $EMPTY, map { pack( 'C', CORE::length ) . $_ } @labels ) . chr( 0 );
}
sub _read_labels_at {
my ( $payload, $offset_ref, $len, $depth ) = @_;
$depth //= 0;
my @labels;
while ( ${$offset_ref} < $len ) {
my $llen = unpack( 'C', substr( $payload, ${$offset_ref}, 1 ) );
if ( $llen == 0 ) {
++${$offset_ref};
last;
}
if ( ( $llen & $DN_COMPRESS_MASK ) == $DN_COMPRESS_MASK ) { ## no critic (Bangs::ProhibitBitwiseOperators ValuesAndExpressions::ProhibitMagicNumbers)
if ( $Net::DHCPv6::Option::FOLLOW_COMPRESSION ) {
Net::DHCPv6::X::Truncated->throw( message => 'Truncated compression pointer' )
if ${$offset_ref} + 2 > $len;
my $ptr =
( ( $llen & $DN_LABEL_MASK ) << 8 ) | unpack( 'C', substr( $payload, ${$offset_ref} + 1, 1 ) ); ## no critic (Bangs::ProhibitBitwiseOperators ValuesAndExpressions::ProhibitMagicNumbers)
Net::DHCPv6::X::BadOption->throw( message => 'Compression pointer out of range' )
if $ptr >= $len;
Net::DHCPv6::X::BadOption->throw( message => 'Compression pointer depth exceeded' )
if $depth > $MAX_PTR_DEPTH;
${$offset_ref} += 2;
my $ptr_ref = \$ptr;
push @labels, _read_labels_at( $payload, $ptr_ref, $len, $depth + 1 );
last;
}
Net::DHCPv6::X::BadOption->throw( message => 'Compression pointer in domain name' );
}
Net::DHCPv6::X::BadOption->throw( message => 'Invalid domain label length' ) if $llen > $DN_LABEL_MASK;
++${$offset_ref};
Net::DHCPv6::X::Truncated->throw( message => 'Truncated domain label' )
if ${$offset_ref} + $llen > $len;
push @labels, substr( $payload, ${$offset_ref}, $llen );
${$offset_ref} += $llen;
}
return @labels;
}
sub _decode_domain {
my ( $payload ) = @_;
return $EMPTY unless CORE::length( $payload );
my $offset = 0;
my @labels = _read_labels_at( $payload, \$offset, CORE::length( $payload ) );
return join( q{.}, @labels );
}
sub new {
my ( $class, %args ) = @_;
croak 'AftrName requires domain_name' unless defined $args{domain_name};
$args{code} = $OPTION_AFTR_NAME;
$args{data} = _encode_domain( $args{domain_name} );
my $self = $class->SUPER::new( %args );
$self->{domain_name} = $args{domain_name};
return bless $self, $class;
}
sub domain_name { return shift->{domain_name} }
( run in 1.291 second using v1.01-cache-2.11-cpan-71847e10f99 )