|
|
b0009a |
Index: lib/Net/DNS/Packet.pm
|
|
|
b0009a |
===================================================================
|
|
|
b0009a |
--- lib/Net/DNS/Packet.pm (revision 1099)
|
|
|
b0009a |
+++ lib/Net/DNS/Packet.pm (working copy)
|
|
|
b0009a |
@@ -30,7 +30,6 @@
|
|
|
b0009a |
use base Exporter;
|
|
|
b0009a |
@EXPORT_OK = qw(dn_expand);
|
|
|
b0009a |
|
|
|
b0009a |
-use strict;
|
|
|
b0009a |
use integer;
|
|
|
b0009a |
use Carp;
|
|
|
b0009a |
|
|
|
b0009a |
@@ -67,7 +66,8 @@
|
|
|
b0009a |
authority => [],
|
|
|
b0009a |
additional => []}, $class;
|
|
|
b0009a |
|
|
|
b0009a |
- $self->{question} = [Net::DNS::Question->new(@_)] if @_;
|
|
|
b0009a |
+ $self->{question} = [Net::DNS::Question->new(@_)] if scalar @_;
|
|
|
b0009a |
+ $self->{header} = {}; # For compatibility with Net::DNS::SEC
|
|
|
b0009a |
|
|
|
b0009a |
$self->header->rd(1);
|
|
|
b0009a |
return $self;
|
|
|
b0009a |
@@ -114,20 +114,23 @@
|
|
|
b0009a |
eval {
|
|
|
b0009a |
die 'corrupt wire-format data' if length($$data) < HEADER_LENGTH;
|
|
|
b0009a |
|
|
|
b0009a |
+ # header section
|
|
|
b0009a |
+ my ( $id, $status, @count ) = unpack 'n6', $$data;
|
|
|
b0009a |
+ my ( $qd, $an, $ns, $ar ) = @count;
|
|
|
b0009a |
+ $offset = HEADER_LENGTH;
|
|
|
b0009a |
+
|
|
|
b0009a |
$self = bless {
|
|
|
b0009a |
+ id => $id,
|
|
|
b0009a |
+ status => $status,
|
|
|
b0009a |
+ count => [@count],
|
|
|
b0009a |
question => [],
|
|
|
b0009a |
answer => [],
|
|
|
b0009a |
authority => [],
|
|
|
b0009a |
additional => [],
|
|
|
b0009a |
- answersize => length $$data
|
|
|
b0009a |
+ answersize => length $$data,
|
|
|
b0009a |
+ header => {} # Compatibility with Net::DNS::SEC
|
|
|
b0009a |
}, $class;
|
|
|
b0009a |
|
|
|
b0009a |
- # header section
|
|
|
b0009a |
- my $header = $self->header;
|
|
|
b0009a |
- $header->decode($data);
|
|
|
b0009a |
- my ( $qd, $an, $ns, $ar ) = map { $header->$_ } qw(qdcount ancount nscount arcount);
|
|
|
b0009a |
- $offset = HEADER_LENGTH;
|
|
|
b0009a |
-
|
|
|
b0009a |
# question/zone section
|
|
|
b0009a |
my $hash = {};
|
|
|
b0009a |
my $record;
|
|
|
b0009a |
@@ -178,18 +181,21 @@
|
|
|
b0009a |
sub data {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
|
|
|
b0009a |
- for ( my $edns = $self->edns ) { # EDNS support
|
|
|
b0009a |
+ my $header = $self->header; # packet header
|
|
|
b0009a |
+ my $ident = $header->id;
|
|
|
b0009a |
+
|
|
|
b0009a |
+ for ( my $edns = $header->edns ) { # EDNS support
|
|
|
b0009a |
my @xopt = grep { $_->type ne 'OPT' } @{$self->{additional}};
|
|
|
b0009a |
$self->{additional} = $edns->default ? [@xopt] : [$edns, @xopt];
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
- my $data = $self->header->encode; # packet header
|
|
|
b0009a |
+ my @part = qw(question answer authority additional);
|
|
|
b0009a |
+ my @size = map scalar( @{$self->{$_}} ), @part;
|
|
|
b0009a |
+ my $data = pack 'n6', $ident, $self->{status}, @size;
|
|
|
b0009a |
+ $self->{count} = [];
|
|
|
b0009a |
|
|
|
b0009a |
my $hash = {}; # packet body
|
|
|
b0009a |
- foreach my $component ( @{$self->{question}},
|
|
|
b0009a |
- @{$self->{answer}},
|
|
|
b0009a |
- @{$self->{authority}},
|
|
|
b0009a |
- @{$self->{additional}} ) {
|
|
|
b0009a |
+ foreach my $component ( map @{$self->{$_}}, @part ) {
|
|
|
b0009a |
$data .= $component->encode( length $data, $hash, $self );
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
@@ -208,8 +214,7 @@
|
|
|
b0009a |
=cut
|
|
|
b0009a |
|
|
|
b0009a |
sub header {
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
- $self->{header} ||= new Net::DNS::Header($self);
|
|
|
b0009a |
+ return new Net::DNS::Header(shift);
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
@@ -243,19 +248,20 @@
|
|
|
b0009a |
sub reply {
|
|
|
b0009a |
my $query = shift;
|
|
|
b0009a |
my $UDPmax = shift;
|
|
|
b0009a |
- die 'erroneous qr flag in query packet' if $query->header->qr;
|
|
|
b0009a |
+ my $qheadr = $query->header;
|
|
|
b0009a |
+ die 'erroneous qr flag in query packet' if $qheadr->qr;
|
|
|
b0009a |
|
|
|
b0009a |
my $reply = new Net::DNS::Packet();
|
|
|
b0009a |
- my $header = $reply->header;
|
|
|
b0009a |
- $header->qr(1); # reply with same id, opcode and question
|
|
|
b0009a |
- $header->id( $query->header->id );
|
|
|
b0009a |
- $header->opcode( $query->header->opcode );
|
|
|
b0009a |
- $reply->{question} = [$query->question];
|
|
|
b0009a |
+ my $rheadr = $reply->header;
|
|
|
b0009a |
+ $rheadr->qr(1); # reply with same id, opcode and question
|
|
|
b0009a |
+ $rheadr->id( $qheadr->id );
|
|
|
b0009a |
+ $rheadr->opcode( $qheadr->opcode );
|
|
|
b0009a |
+ $reply->{question} = $query->{question};
|
|
|
b0009a |
|
|
|
b0009a |
- $header->rcode('FORMERR'); # failure to provide RCODE is sinful!
|
|
|
b0009a |
+ $rheadr->rcode('FORMERR'); # failure to provide RCODE is sinful!
|
|
|
b0009a |
|
|
|
b0009a |
- $header->rd( $query->header->rd ); # copy these flags into reply
|
|
|
b0009a |
- $header->cd( $query->header->cd );
|
|
|
b0009a |
+ $rheadr->rd( $qheadr->rd ); # copy these flags into reply
|
|
|
b0009a |
+ $rheadr->cd( $qheadr->cd );
|
|
|
b0009a |
|
|
|
b0009a |
$reply->edns->size($UDPmax) unless $query->edns->default;
|
|
|
b0009a |
return $reply;
|
|
|
b0009a |
@@ -405,7 +411,7 @@
|
|
|
b0009a |
sub answerfrom {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
|
|
|
b0009a |
- return $self->{answerfrom} = shift if @_;
|
|
|
b0009a |
+ return $self->{answerfrom} = shift if scalar @_;
|
|
|
b0009a |
|
|
|
b0009a |
return $self->{answerfrom};
|
|
|
b0009a |
}
|
|
|
b0009a |
@@ -778,7 +784,7 @@
|
|
|
b0009a |
my $i=0;
|
|
|
b0009a |
my @stripped_additonal;
|
|
|
b0009a |
|
|
|
b0009a |
- while ($i< @{$self->{'additional'}}){
|
|
|
b0009a |
+ while ( $i < scalar @{$self->{'additional'}} ) {
|
|
|
b0009a |
#remove all of these same RRtypes
|
|
|
b0009a |
if (
|
|
|
b0009a |
${$self->{'additional'}}[$i]->type eq $popped->type &&
|
|
|
b0009a |
@@ -814,21 +820,16 @@
|
|
|
b0009a |
|
|
|
b0009a |
use vars qw($AUTOLOAD);
|
|
|
b0009a |
|
|
|
b0009a |
-sub AUTOLOAD { ## Default method
|
|
|
b0009a |
+sub AUTOLOAD { ## Default method
|
|
|
b0009a |
no strict;
|
|
|
b0009a |
@_ = ("method $AUTOLOAD undefined");
|
|
|
b0009a |
goto &{'Carp::confess'};
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
-sub DESTROY { ## object destructor
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
- my $header = $self->header; # invalidate Header object
|
|
|
b0009a |
- %$header = ();
|
|
|
b0009a |
- undef $self->{header}; # unlink defunct header
|
|
|
b0009a |
-}
|
|
|
b0009a |
+sub DESTROY { } ## Avoid tickling AUTOLOAD (in cleanup)
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
-sub dump { ## print internal data structure
|
|
|
b0009a |
+sub dump { ## print internal data structure
|
|
|
b0009a |
use Data::Dumper;
|
|
|
b0009a |
$Data::Dumper::Sortkeys = sub { return [sort keys %{$_[0]}] };
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
Index: lib/Net/DNS/Header.pm
|
|
|
b0009a |
===================================================================
|
|
|
b0009a |
--- lib/Net/DNS/Header.pm (revision 1099)
|
|
|
b0009a |
+++ lib/Net/DNS/Header.pm (working copy)
|
|
|
b0009a |
@@ -51,56 +51,10 @@
|
|
|
b0009a |
|
|
|
b0009a |
croak 'object model violation' unless $packet->isa(qw(Net::DNS::Packet));
|
|
|
b0009a |
|
|
|
b0009a |
- my $self = bless {
|
|
|
b0009a |
- status => 0,
|
|
|
b0009a |
- count => [],
|
|
|
b0009a |
- xbody => $packet
|
|
|
b0009a |
- }, $class;
|
|
|
b0009a |
-
|
|
|
b0009a |
- $self->id(undef);
|
|
|
b0009a |
-
|
|
|
b0009a |
- return $self;
|
|
|
b0009a |
+ bless { xbody => $packet }, $class;
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
-=head2 decode
|
|
|
b0009a |
-
|
|
|
b0009a |
- $header->decode(\$data);
|
|
|
b0009a |
-
|
|
|
b0009a |
-Decodes the header record at the start of a DNS packet.
|
|
|
b0009a |
-The argument is a reference to the packet data.
|
|
|
b0009a |
-
|
|
|
b0009a |
-=cut
|
|
|
b0009a |
-
|
|
|
b0009a |
-sub decode {
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
- my $data = shift;
|
|
|
b0009a |
-
|
|
|
b0009a |
- @{$self}{qw(id status)} = unpack 'n2', $$data;
|
|
|
b0009a |
- $self->{count} = [unpack 'x4 n6', $$data];
|
|
|
b0009a |
-}
|
|
|
b0009a |
-
|
|
|
b0009a |
-
|
|
|
b0009a |
-=head2 encode
|
|
|
b0009a |
-
|
|
|
b0009a |
- $header->encode(\$data);
|
|
|
b0009a |
-
|
|
|
b0009a |
-Returns the header data in binary format, appropriate for use in a
|
|
|
b0009a |
-DNS packet.
|
|
|
b0009a |
-
|
|
|
b0009a |
-=cut
|
|
|
b0009a |
-
|
|
|
b0009a |
-sub encode {
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
-
|
|
|
b0009a |
- $self->{count} = [];
|
|
|
b0009a |
-
|
|
|
b0009a |
- my @count = map { $self->$_ } qw(qdcount ancount nscount arcount);
|
|
|
b0009a |
-
|
|
|
b0009a |
- return pack 'n6', $self->{id}, $self->{status}, @count;
|
|
|
b0009a |
-}
|
|
|
b0009a |
-
|
|
|
b0009a |
-
|
|
|
b0009a |
=head2 string
|
|
|
b0009a |
|
|
|
b0009a |
print $packet->header->string;
|
|
|
b0009a |
@@ -121,11 +75,15 @@
|
|
|
b0009a |
my $ns = $self->nscount;
|
|
|
b0009a |
my $ar = $self->arcount;
|
|
|
b0009a |
|
|
|
b0009a |
+ my $opt = $self->edns;
|
|
|
b0009a |
+ my $edns = ( $opt->isa(qw(Net::DNS::RR::OPT)) && not $opt->default ) ? $opt->string : '';
|
|
|
b0009a |
+
|
|
|
b0009a |
my $retval;
|
|
|
b0009a |
return $retval = <
|
|
|
b0009a |
;; id = $id
|
|
|
b0009a |
;; qr = $qr opcode = $opcode rcode = $rcode
|
|
|
b0009a |
;; zocount = $qd prcount = $an upcount = $ns adcount = $ar
|
|
|
b0009a |
+$edns
|
|
|
b0009a |
EOF
|
|
|
b0009a |
|
|
|
b0009a |
my $aa = $self->aa;
|
|
|
b0009a |
@@ -137,9 +95,6 @@
|
|
|
b0009a |
my $cd = $self->cd;
|
|
|
b0009a |
my $do = $self->do;
|
|
|
b0009a |
|
|
|
b0009a |
- my $opt = $self->edns;
|
|
|
b0009a |
- my $edns = ( $opt->isa(qw(Net::DNS::RR::OPT)) && not $opt->default ) ? $opt->string : '';
|
|
|
b0009a |
-
|
|
|
b0009a |
return $retval = <
|
|
|
b0009a |
;; id = $id
|
|
|
b0009a |
;; qr = $qr aa = $aa tc = $tc rd = $rd opcode = $opcode
|
|
|
b0009a |
@@ -166,8 +121,9 @@
|
|
|
b0009a |
|
|
|
b0009a |
sub id {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
- return $self->{id} unless @_;
|
|
|
b0009a |
- return $self->{id} = shift || int rand(0xffff);
|
|
|
b0009a |
+ my $xpkt = $self->{xbody};
|
|
|
b0009a |
+ $xpkt->{id} = shift if scalar @_;
|
|
|
b0009a |
+ $xpkt->{id} ||= int rand(0xffff);
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
@@ -182,8 +138,9 @@
|
|
|
b0009a |
|
|
|
b0009a |
sub opcode {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
- for ( $self->{status} ) {
|
|
|
b0009a |
- return opcodebyval( ( $_ >> 11 ) & 0x0f ) unless @_;
|
|
|
b0009a |
+ my $xpkt = $self->{xbody};
|
|
|
b0009a |
+ for ( $xpkt->{status} ||= 0 ) {
|
|
|
b0009a |
+ return opcodebyval( ( $_ >> 11 ) & 0x0f ) unless scalar @_;
|
|
|
b0009a |
my $opcode = opcodebyname(shift);
|
|
|
b0009a |
$_ = ( $_ & 0x87ff ) | ( $opcode << 11 );
|
|
|
b0009a |
return $opcode;
|
|
|
b0009a |
@@ -202,7 +159,8 @@
|
|
|
b0009a |
|
|
|
b0009a |
sub rcode {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
- for ( $self->{status} ) {
|
|
|
b0009a |
+ my $xpkt = $self->{xbody};
|
|
|
b0009a |
+ for ( $xpkt->{status} ||= 0 ) {
|
|
|
b0009a |
my $arg = shift;
|
|
|
b0009a |
my $opt = $self->edns;
|
|
|
b0009a |
unless ( defined $arg ) {
|
|
|
b0009a |
@@ -335,7 +293,7 @@
|
|
|
b0009a |
|
|
|
b0009a |
print "# of question records: ", $packet->header->qdcount, "\n";
|
|
|
b0009a |
|
|
|
b0009a |
-Gets the number of records in the question section of the packet.
|
|
|
b0009a |
+Returns the number of records in the question section of the packet.
|
|
|
b0009a |
In dynamic update packets, this field is known as C<zocount> and refers
|
|
|
b0009a |
to the number of RRs in the zone section.
|
|
|
b0009a |
|
|
|
b0009a |
@@ -346,7 +304,7 @@
|
|
|
b0009a |
sub qdcount {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $xpkt = $self->{xbody};
|
|
|
b0009a |
- return $self->{count}[0] || scalar @{$xpkt->{question}} unless @_;
|
|
|
b0009a |
+ return $xpkt->{count}[0] || scalar @{$xpkt->{question}} unless scalar @_;
|
|
|
b0009a |
carp 'header->qdcount attribute is read-only' unless $warned;
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
@@ -366,7 +324,7 @@
|
|
|
b0009a |
sub ancount {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $xpkt = $self->{xbody};
|
|
|
b0009a |
- return $self->{count}[1] || scalar @{$xpkt->{answer}} unless @_;
|
|
|
b0009a |
+ return $xpkt->{count}[1] || scalar @{$xpkt->{answer}} unless scalar @_;
|
|
|
b0009a |
carp 'header->ancount attribute is read-only' unless $warned;
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
@@ -386,7 +344,7 @@
|
|
|
b0009a |
sub nscount {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $xpkt = $self->{xbody};
|
|
|
b0009a |
- return $self->{count}[2] || scalar @{$xpkt->{authority}} unless @_;
|
|
|
b0009a |
+ return $xpkt->{count}[2] || scalar @{$xpkt->{authority}} unless scalar @_;
|
|
|
b0009a |
carp 'header->nscount attribute is read-only' unless $warned;
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
@@ -405,7 +363,7 @@
|
|
|
b0009a |
sub arcount {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $xpkt = $self->{xbody};
|
|
|
b0009a |
- return $self->{count}[3] || scalar @{$xpkt->{additional}} unless @_;
|
|
|
b0009a |
+ return $xpkt->{count}[3] || scalar @{$xpkt->{additional}} unless scalar @_;
|
|
|
b0009a |
carp 'header->arcount attribute is read-only' unless $warned;
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
@@ -469,11 +427,11 @@
|
|
|
b0009a |
=cut
|
|
|
b0009a |
|
|
|
b0009a |
sub edns {
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
- my $xpkt = $self->{xbody};
|
|
|
b0009a |
- my $xtender = \$self->{xtender};
|
|
|
b0009a |
- ($$xtender) = grep { $_->type eq 'OPT' } @{$xpkt->{additional}} unless $$xtender;
|
|
|
b0009a |
- return $$xtender ||= new Net::DNS::RR('. OPT');
|
|
|
b0009a |
+ my $self = shift;
|
|
|
b0009a |
+ my $xpkt = $self->{xbody};
|
|
|
b0009a |
+ my $link = \$xpkt->{xedns};
|
|
|
b0009a |
+ ($$link) = grep { $_->type eq 'OPT' } @{$xpkt->{additional}} unless $$link;
|
|
|
b0009a |
+ return $$link ||= new Net::DNS::RR('. OPT');
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
@@ -481,31 +439,23 @@
|
|
|
b0009a |
|
|
|
b0009a |
use vars qw($AUTOLOAD);
|
|
|
b0009a |
|
|
|
b0009a |
-sub AUTOLOAD { ## Default method
|
|
|
b0009a |
+sub AUTOLOAD { ## Default method
|
|
|
b0009a |
no strict;
|
|
|
b0009a |
@_ = ("method $AUTOLOAD undefined");
|
|
|
b0009a |
goto &{'Carp::confess'};
|
|
|
b0009a |
}
|
|
|
b0009a |
|
|
|
b0009a |
-sub DESTROY { } ## Avoid tickling AUTOLOAD (in cleanup)
|
|
|
b0009a |
+sub DESTROY { } ## Avoid tickling AUTOLOAD (in cleanup)
|
|
|
b0009a |
|
|
|
b0009a |
|
|
|
b0009a |
-sub dump { ## print internal data structure
|
|
|
b0009a |
- use Data::Dumper;
|
|
|
b0009a |
- $Data::Dumper::Sortkeys = sub { return [sort keys %{$_[0]}] };
|
|
|
b0009a |
- my $self = shift;
|
|
|
b0009a |
- return Dumper($self) if defined wantarray;
|
|
|
b0009a |
- print Dumper($self);
|
|
|
b0009a |
-}
|
|
|
b0009a |
-
|
|
|
b0009a |
-
|
|
|
b0009a |
sub _dnsflag {
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $flag = shift;
|
|
|
b0009a |
- for ( $self->{status} ) {
|
|
|
b0009a |
+ my $xpkt = $self->{xbody};
|
|
|
b0009a |
+ for ( $xpkt->{status} ||= 0 ) {
|
|
|
b0009a |
my $set = $_ | $flag;
|
|
|
b0009a |
my $not = $set - $flag;
|
|
|
b0009a |
- $_ = (shift) ? $set : $not if @_;
|
|
|
b0009a |
+ $_ = (shift) ? $set : $not if scalar @_;
|
|
|
b0009a |
return ( $_ & $flag ) ? 1 : 0;
|
|
|
b0009a |
}
|
|
|
b0009a |
}
|
|
|
b0009a |
@@ -515,7 +465,7 @@
|
|
|
b0009a |
my $self = shift;
|
|
|
b0009a |
my $flag = shift;
|
|
|
b0009a |
my $edns = eval { $self->edns->flags } || 0;
|
|
|
b0009a |
- return $flag & $edns ? 1 : 0 unless @_;
|
|
|
b0009a |
+ return $flag & $edns ? 1 : 0 unless scalar @_;
|
|
|
b0009a |
my $set = $flag | $edns;
|
|
|
b0009a |
my $not = $set - $flag;
|
|
|
b0009a |
my $new = (shift) ? $set : $not;
|