Current Path : /usr/local/lib/perl5/site_perl/5.8.9/mach/Net/DNS/RR/APL/ |
FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64 |
Current File : //usr/local/lib/perl5/site_perl/5.8.9/mach/Net/DNS/RR/APL/ApItem.pm |
package Net::DNS::RR::APL::ApItem; # # $Id: ApItem.pm 764 2008-12-24 09:36:37Z olaf $ # use Net::DNS::Resolver::Base; use Socket; use strict; BEGIN { eval { require bytes; } } use vars qw(@ISA $VERSION); @ISA = qw(Net::DNS::RR); $VERSION = (qw$LastChangedRevision: 684 $)[1]; use Data::Dumper; =head1 NAME Net::DNS::RR::APL::ApItem - DNS APL ApItem =head1 SYNOPSIS use Net::DNS::RR::APL::ApItem; my $apitem=Net::DNS::RR::APL::ApItem->new(); =head1 DESCRIPTION This is an object that contains the Address Prefixes with related information such as address family and possible negation flags for the APL RR. Please see the RFC3123 for details. =head1 Methods =head2 new Constructor method. $apitem[0]=Net::DNS::RR::APL::ApItem->new(1:192.168.32.0/21); $apitem[1]=Net::DNS::RR::APL::ApItem->new(!1:192.168.32.0/21); $apitem[2]=Net::DNS::RR::APL::ApItem->new(2:FF00:0:0:0:0:0:0:0/8); $empty=Net::DNS::RR::APL::ApItem(); Returns undef if the argument cannot be parsed. Returns an object with empty attributes when no argument is supplied. =cut sub new { my $caller = shift; my $class = ref($caller) || $caller; my $self={ address => '', addressfamily => '', negation => '', prefix => '', }; my $input=shift; bless $self, $class; return $self->parse($input) if defined($input); # returns undef when parse fails return $self; } # The textual representation of an APL RR in a DNS zone file is as # follows: # # <owner> IN <TTL> APL {[!]afi:address/prefix}* # # The data consists of zero or more strings of the address family # indicator <afi>, immediately followed by a colon ":", an address, # immediately followed by the "/" character, immediately followed by a # decimal numeric value for the prefix length. Any such string may be # preceded by a "!" character. The strings are separated by # whitespace. The <afi> is the decimal numeric value of that # particular address family. sub parse { my $self=shift; my $input=shift; if($input=~/(!?)([12])\:(.+)\/(\d{1,3})/){ my $negation=$1; my $addressfamily=$2; my $address=$3; my $prefix=$4; # Sanity check return if ( ($addressfamily == 1) && (! Net::DNS::Resolver::Base::_ip_is_ipv4($address) || $prefix > 32 )); return if ( ($addressfamily == 2) && (! Net::DNS::Resolver::Base::_ip_is_ipv6($address) || $prefix > 128 )); return if ( $addressfamily > 2 ); $self->address($address); $self->addressfamily($addressfamily); $self->prefix($prefix); $self->negation($negation); return $self; } #Pattern match failed. return; } sub print { print &string, "\n"; } =head2 string Returns a string representation of the object in the '[!]afi:address/prefix' format $apl=$apitem[0]->string; =head2 print Prints the textual representation of the object. $apitem[0]->print; # same functionality as: $apl=$apitem[0]->string; print $apl; =cut sub string { my $self=shift; my $dat= $self->negation ? "!" : ""; $dat .= $self->addressfamily() .":" . $self->address."/".$self->prefix; return $dat; } # APL RDATA format # # The RDATA section consists of zero or more items (<apitem>) of the # form # # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ # | ADDRESSFAMILY | # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ # | PREFIX | N | AFDLENGTH | # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ # / AFDPART / # | | # +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ # # ADDRESSFAMILY 16 bit unsigned value as assigned by IANA # (see IANA Considerations) # PREFIX 8 bit unsigned binary coded prefix length. # Upper and lower bounds and interpretation of # this value are address family specific. # N negation flag, indicates the presence of the # "!" character in the textual format. It has # the value "1" if the "!" was given, "0" else. # AFDLENGTH length in octets of the following address # family dependent part (7 bit unsigned). # AFDPART address family dependent part. See below. # # @self sub rdata { my $self=shift; my $rdata; return unless ((exists $self->{'addressfamily'}) && (exists $self->{'address'}) && (exists $self->{'prefix'})); if ($self->{'addressfamily'}==1){ $rdata=pack ("n",0x0001); $rdata.=pack ("C",$self->prefix()); my $data .= &stripzerobytes(inet_aton($self->address())); $rdata.=pack("C", ($self->negation()? (0x80|length($data)):length($data) )); $rdata.=$data; }elsif ($self->{'addressfamily'}==2){ $rdata=pack ("n",0x0002); $rdata.=pack ("C",$self->prefix()); my @addr = split(/:/, $self->{"address"}); my $data=&stripzerobytes(pack("n8", map { hex $_ } @addr )); $rdata.=pack("C", ($self->negation()? (0x80|length($data)):length($data) )); $rdata.=$data; }else{ #NOT Defined, return empty A data return; } return $rdata; } sub stripzerobytes { my @a = unpack('C*',shift); my @b; my $notseenval=1; while (defined(my $a=pop( @a))){ unshift @b,$a unless ($a==0 && $notseenval); next unless $notseenval; $notseenval= !$a; } return pack("C*",@b); } sub new_from_wire { my $caller = shift; my $class = ref($caller) || $caller; my ($data, $offset) = @_; my $orgoffset=$offset; my $self={ address => '', addressfamily => '', negation => '', prefix => '', }; bless $self, $class; $self->addressfamily( unpack('n',substr($data,$offset,2))); $offset+=2; $self->prefix( unpack('C',substr($data,$offset,1))); $offset+=1; my $negandlength=unpack('C',substr($data,$offset,1)); $self->negation( 0x80 == ( $negandlength & 0x80)); $offset+=1; my $length= $negandlength & 0x7f; return if (length($data)< $offset+$length); if ($self->addressfamily==1){ # pack(Cy,unpack("C*",$foo)) is a hack to pad with trailing 0s. $self->{"address"} = inet_ntoa( pack("C4",unpack("C*",substr($data, $offset,$length) ))); }elsif($self->addressfamily==2){ my $extracted=substr($data, $offset,$length); # pack(Cy,unpack("C*",$foo)) is a hack to pad with trailing 0s. my @addr = unpack("n8", pack("C16",unpack("C*",substr($data, $offset,$length) ))); $self->{"address"} = sprintf("%x:%x:%x:%x:%x:%x:%x:%x", @addr); }else{ #FORMERR return; } $offset+=$length; return $self,$offset; } =head1 COPYRIGHT Copyright (c) 2008 Olaf Kolkman (NLnet Labs) All rights reserved. This program is free software; you may redistribute it and/or modify it under the same terms as Perl itself. =head1 SEE ALSO L<Net::DNS::RR::APL>, L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>, L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>, RFC 3123 =cut