Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 33547
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: cpan [...] aaroncrane.co.uk
tyronmiller [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: Net::DNS::Nameserver doesn't truncate long UDP replies [PATCH]
Net::DNS::Nameserver never attempts to apply the UDP truncation logic required by RFC 1035 sections 4.2.1 and 6.2. It's impossible for the ReplyHandler to work around this, because it never has access to the socket on which the query was received, and so can't determine whether it's a datagram or stream socket. The attached patch against SVN r715 contains: - Tests for the desired truncation behaviour, with both standard 512-byte UDP packets and extended 1024-byte UDP packets (using an EDNS0 OPT record) - Changes to lib/Net/DNS/Nameserver.pm to truncate oversized responses; the tests fail without these changes, and pass with them Summary of my perl5 (revision 5 version 8 subversion 8) configuration: Platform: osname=linux, osvers=2.6.15.7, archname=i486-linux-gnu-thread-multi uname='linux terranova 2.6.15.7 #1 smp thu jul 12 14:27:56 utc 2007 i686 gnulinux ' config_args='-Dusethreads -Duselargefiles -Dccflags=-DDEBIAN -Dcccdlflags=-fPIC -Darchname=i486-linux-gnu -Dprefix=/usr -Dprivlib=/usr/share/perl/5.8 -Darchlib=/usr/lib/perl/5.8 -Dvendorprefix=/usr -Dvendorlib=/usr/share/perl5 -Dvendorarch=/usr/lib/perl5 -Dsiteprefix=/usr/local -Dsitelib=/usr/local/share/perl/5.8.8 -Dsitearch=/usr/local/lib/perl/5.8.8 -Dman1dir=/usr/share/man/man1 -Dman3dir=/usr/share/man/man3 -Dsiteman1dir=/usr/local/man/man1 -Dsiteman3dir=/usr/local/man/man3 -Dman1ext=1 -Dman3ext=3perl -Dpager=/usr/bin/sensible-pager -Uafs -Ud_csh -Uusesfio -Uusenm -Duseshrplib -Dlibperl=libperl.so.5.8.8 -Dd_dosuid -des' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemultiplicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64', optimize='-O2', cppflags='-D_REENTRANT -D_GNU_SOURCE -DTHREADS_HAVE_PIDS -DDEBIAN -fno-strict-aliasing -pipe -I/usr/local/include' ccversion='', gccversion='4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8 alignbytes=4, prototype=define Linker and Libraries: ld='cc', ldflags =' -L/usr/local/lib' libpth=/usr/local/lib /lib /usr/lib libs=-lgdbm -lgdbm_compat -ldb -ldl -lm -lpthread -lc -lcrypt perllibs=-ldl -lm -lpthread -lc -lcrypt libc=/lib/libc-2.6.1.so, so=so, useshrplib=true, libperl=libperl.so.5.8.8 gnulibc_version='2.6.1' Dynamic Linking: dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E' cccdlflags='-fPIC', lddlflags='-shared -L/usr/local/lib' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP THREADS_HAVE_PIDS USE_ITHREADS USE_LARGE_FILES USE_PERLIO USE_REENTRANT_API Built under linux Compiled at Dec 4 2007 08:56:39 @INC: /etc/perl /usr/local/lib/perl/5.8.8 /usr/local/share/perl/5.8.8 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.8 /usr/share/perl/5.8 /usr/local/lib/site_perl .
Subject: udp_truncation.diff
Index: lib/Net/DNS/Nameserver.pm =================================================================== --- lib/Net/DNS/Nameserver.pm (revision 715) +++ lib/Net/DNS/Nameserver.pm (working copy) @@ -355,6 +355,20 @@ my $reply = $self->make_reply($query, $peerhost) || return; my $reply_data = $reply->data; + my $max_len = $self->max_udp_len($query); + if (length $reply_data > $max_len) { + $reply->header->tc(1); + my @sections = qw<additional authority answer question>; + while (@sections) { + if (!$reply->pop($sections[0])) { + shift @sections; + next; + } + $reply_data = $reply->data; + last if length $reply_data <= $max_len; + } + } + local $| = 1 if $self->{"Verbose"}; print "Writing response - " if $self->{"Verbose"}; @@ -367,6 +381,17 @@ } +sub max_udp_len { + my ($self, $query) = @_; + + for my $rr ($query->additional) { + return $rr->size if $rr->type eq 'OPT'; + } + + return 512; +} + + sub get_open_tcp { my $self=shift; return keys %{$self->{"_tcp"}}; Index: t/13-udp-trunc.t =================================================================== --- t/13-udp-trunc.t (revision 0) +++ t/13-udp-trunc.t (revision 0) @@ -0,0 +1,121 @@ +# $Id$ -*- perl + +use Test::More tests => 31; +use strict; + +my $ZONE = 'example.com'; + +use_ok('Net::DNS::Nameserver'); + +{ + my @full_response; + my $ns = Net::DNS::Nameserver->new( + LocalPort => 8053, + ReplyHandler => sub { NOERROR => @full_response }, + ); + for (trad_query(), edns_query()) { + my ($query, $size) = @$_; + for my $n (1, 5, 10, 50, 200) { + @full_response = make_response($n); + my $socket = Mock::UDP->new($query->data); + $ns->udp_connection($socket); + my $reply_data = $socket->output; + cmp_ok(length $reply_data, '<=', $size, + "UDP-$size reply for $n A records short enough"); + my $reply = Net::DNS::Packet->new(\$reply_data); + ok($reply, "found UDP-$size reply for $n A records"); + my $got = reply_records($reply); + my $expected = response_records($query, @full_response); + ok(is_prefix($reply->header->tc, $got, $expected), + "UDP-$size reply for $n A records complete or sanely truncated"); + } + } +} + +sub trad_query { + return [Net::DNS::Packet->new($ZONE), 512]; +} + +sub edns_query { + my $size = 1024; + my $edns_rr = Net::DNS::RR->new(type => 'OPT', class => $size, name => ''); + my $query = Net::DNS::Packet->new($ZONE); + $query->push(additional => $edns_rr); + return [$query, $size]; +} + +sub reply_records { + my ($reply) = @_; + my @records; + for my $section (qw<question answer authority additional>) { + push @records, map { [$section => $_] } $reply->$section; + } + return \@records; +} + +sub response_records { + my ($query, @response) = @_; + unshift @response, [$query->question]; + my @records; + for my $section (qw<question answer authority additional>) { + push @records, map { [$section => $_] } @{ shift @response }; + } + return \@records; +} + +sub is_prefix { + my ($truncated, $got_list, $expected_list) = @_; + die 'TEST BUG: no records expected' if !@$expected_list; + if (@$got_list > @$expected_list) { + diag("Most peculiar: got too many records"); + return 0; + } + for (;;) { + return !$truncated == !@$expected_list if !@$got_list; + my $got = shift @$got_list; + my $expected = shift @$expected_list; + my ($got_s, $expected_s) = map { $_->[1]->string } $got, $expected; + next if $got->[0] eq $expected->[0] && $got_s eq $expected_s; + if ($got->[0] ne $expected->[0] || $got_s ne $expected_s) { + diag("Got[$got->[0] $got_s] Expected[$expected->[0] $expected_s]"); + return 0; + } + } +} + +sub make_response { + my ($n) = @_; + my @ans = map { Net::DNS::RR->new("$ZONE 9 IN A 10.0.0.$_") } 1 .. $n; + my @auth = map { Net::DNS::RR->new("$ZONE 9 IN NS ns$_.$ZONE") } 1 .. 4; + my @add = map { Net::DNS::RR->new("ns$_.$ZONE 9 IN A 10.0.1.$_") } 1 .. 4; + return \@ans, \@auth, \@add; +} + +{ + package Mock::UDP; + + sub new { + my ($class, $data) = @_; + return bless { + input => $data, + output => '', + }, $class; + } + + sub peerhost { '127.0.0.1' } + sub peerport { 65534 } + sub output { $_[0]{output} } + + sub recv { + my ($self, $buf, $len) = @_; + return if $self->{input} eq ''; + my $data = substr $self->{input}, 0, $len, ''; + $_[1] = $data; + } + + sub send { + my ($self, $data) = @_; + $self->{output} .= $data; + 1; + } +}
Subject: Re: [rt.cpan.org #33547] Net::DNS::Nameserver doesn't truncate long UDP replies [PATCH]
Date: Tue, 26 Feb 2008 08:29:18 +0100
To: bug-Net-DNS [...] rt.cpan.org
From: "Olaf M. Kolkman" <olaf [...] dacht.net>
Aaron Crane via RT wrote: Show quoted text
> Sun Feb 24 09:22:28 2008: Request 33547 was acted upon. > Transaction: Ticket created by ARC > Queue: Net-DNS > Subject: Net::DNS::Nameserver doesn't truncate long UDP replies [PATCH] > Broken in: (no value) > Severity: Important > Owner: Nobody > Requestors: cpan@aaroncrane.co.uk > Status: new > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=33547 > > > > Net::DNS::Nameserver never attempts to apply the UDP truncation logic > required by RFC 1035 sections 4.2.1 and 6.2. > > It's impossible for the ReplyHandler to work around this, because it > never has access to the socket on which the query was received, and so > can't determine whether it's a datagram or stream socket. > > The attached patch against SVN r715 contains: > > - Tests for the desired truncation behaviour, with both standard > 512-byte UDP packets and extended 1024-byte UDP packets (using an EDNS0 > OPT record) > > - Changes to lib/Net/DNS/Nameserver.pm to truncate oversized responses; > the tests fail without these changes, and pass with them >
Thanks for the patch, however. Truncation as supplied in the patch does two simplyfications. One of the issues is that the patch blindly sets the TC bit in the header while the overflow may have happened in the additional section. (RFC2181 section 9 provides guidance on when to set the TC bit). This is fairly easy to fix by first popping additional section data, and only if that has no effect set the TC bit. Also the patch pops RR by RR from the sections, while to be compliant to the specification you will have to pop RRset by RRset (and RRset is the set of RRs for which Name, Class and Type are the same). Since the RRs in an RRset do not necessarily have to be clustered within a section you really need to parse a complete section to strip correctly. One could take the assumption that the RRs are bundled. Also, I would have to check if one strips an RRSIG one has to include the signed RRset as well, that should be buried somewhere in the specs. It may be better to supply the user with hooks in the callback function or an additional callback so that the user can adjust the packet themselves. I appreciate the initiative and having something done with truncation is better than nothing, but I would like to ponder on a solution for a bit. --Olaf
Download signature.asc
application/pgp-signature 252b

Message body not shown because it is not plain text.

Subject: Net::DNS::Header->tc(1) doesn't set Trucation flag
I am trying to send large DNS responses, which means I need to set the "tc" flag so that the transport changes from UDP to TCP due to truncated data. When using the following code, the header data is printed out with the "tc" flag set; however, in Wireshark the flag is still shown to be off and the transport does not get redirected to TCP by the requesting DNS server. [snip] $header = Net::DNS::Header->new; $header->aa(1); # sets aa flag in both printed output and wireshark $header->tc(1); # sets tc flag in printed output, but not wireshark $header->print; # prints both flags as being set, but tc not shown in wireshark my @response = ($rcode, \@ans, \@auth, \@add, $header); return @response; #end reply handler I am using version 0.63, and I checked the changelog for 0.64 but there was no mention of a bug fix for this issue.
Subject: Re: [rt.cpan.org #42744] Net::DNS::Header->tc(1) doesn't set Trucation flag
Date: Sat, 24 Jan 2009 11:41:58 +0100
To: bug-Net-DNS [...] rt.cpan.org
From: Olaf Kolkman <olaf [...] dacht.net>
I take it that you are trying to construct a reply handler. The ReplyHandler subroutine is passed the query name, query class, query type and optionally an argument containing the peerhost, the incoming query, and the name of the incomming socket (sockethost). It must return the response code and references to the answer, authority, and additional sections of the response. Common response codes are: NOERROR No error FORMERR Format error SERVFAIL Server failure NXDOMAIN Non‐existent domain (name doesn’t exist) NOTIMP Not implemented REFUSED Query refused For advanced usage it may also contain a headermaks containing an hashref with the settings for the "aa", "ra", and "ad" header bits. The argument is of the form "{ ad => 1, aa => 0, ra => 1 }". The argument that tweaks the bits is not a header object but a reference to a hash containing the header values. Here is a code sniplet from Net::DNS::TestNS that sets the arguments and uses the headermask, maybe that is of use. # The XML has been parsed and all info sits in the %answer db.. # We now construct the reply handler using that. my $reply_handler = sub { my ($qname, $qclass, $qtype) = @_; $qname.="." if $qname !~ /\.$/; my ($rcode, @ans, @auth, @add); if ( exists $answerdb{$qname}->{$qtype}){ $rcode= $answerdb{$qname}->{$qtype}->{'rcode'}; my $transporthash= { 'aa' => $answerdb{$qname}->{$qtype}-> {'header'}->{'aa'}, 'ra' => $answerdb{$qname}->{$qtype}-> {'header'}->{'ra'}, }; foreach my $headerfield qw(aa qr ad rd tc id cd qdcount ancount nscount arcount ){ $transporthash->{$headerfield}= $answerdb{$qname}->{$qtype}-> {'header'}->{$headerfield} if defined $answerdb{$qname}->{$qtype}->{'header'}->{$headerfield} ; } print "Sleeping for " . $answerdb{$qname}->{$qtype}->{'delay'} . " seconds " if $self->{verbose} && $answerdb{$qname}->{$qtype}->{'delay'}; sleep ($answerdb{$qname}->{$qtype}->{'delay'}); if (defined($answerdb{$qname}->{$qtype}->{'raw'})){ $transporthash->{'raw'}=$answerdb{$qname}->{$qtype}->{'raw'}; } return ($rcode, $answerdb{$qname}->{$qtype}->{'answer'}, $answerdb{$qname}->{$qtype}->{'authority'}, $answerdb{$qname}->{$qtype}->{'additional'}, $transporthash); } return ("SERVFAIL"); }; Hope this helps, --Olaf On Jan 24, 2009, at 3:55 AM, Ty Miller via RT wrote: Show quoted text
> Fri Jan 23 21:55:01 2009: Request 42744 was acted upon. > Transaction: Ticket created by tyronmiller > Queue: Net-DNS > Subject: Net::DNS::Header->tc(1) doesn't set Trucation flag > Broken in: 0.63 > Severity: Important > Owner: Nobody > Requestors: tyronmiller@gmail.com > Status: new > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > > > > I am trying to send large DNS responses, which means I need to set the > "tc" flag so that the transport changes from UDP to TCP due to > truncated > data. When using the following code, the header data is printed out > with > the "tc" flag set; however, in Wireshark the flag is still shown to be > off and the transport does not get redirected to TCP by the requesting > DNS server. > > [snip] > $header = Net::DNS::Header->new; > $header->aa(1); # sets aa flag in both printed output and wireshark > $header->tc(1); # sets tc flag in printed output, but not wireshark > $header->print; # prints both flags as being set, but tc not shown in > wireshark > my @response = ($rcode, \@ans, \@auth, \@add, $header); > return @response; > #end reply handler > > I am using version 0.63, and I checked the changelog for 0.64 but > there > was no mention of a bug fix for this issue.
Download PGP.sig
application/pgp-signature 194b

Message body not shown because it is not plain text.

Subject: Re: [rt.cpan.org #42744] Net::DNS::Header->tc(1) doesn't set Trucation flag
Date: Tue, 27 Jan 2009 19:23:53 +1100
To: bug-Net-DNS [...] rt.cpan.org
From: Ty Miller <tyronmiller [...] gmail.com>
Hi Olaf, Thanks so much for the quick and detailed response. Yes, I have implemented a ReplyHandler which works fine, except that the responses I am sending are larger than 512 bytes, so i'm trying to set the truncation bit (tc) so that the protocol falls back to TCP, which should allow me to send large DNS responses. I can see how you have used the "transporthash" in the code. Sorry about my misunderstanding. Originally I was doing this; however, I tried to set the tc bit directly in the hash ... like ... { aa => 1, tc => 1} ... which obviously didn't work. I implemented the technique shown below where it sets the hash and then loops through the other flags (including tc); however, I am still struggling to get it to work. Some of the other flags seem to get set, but the tc flag is still not being set - as shown by wireshark. The only difference to the implementation that you provied was that I didn't have the "answerdb", and simply set the header field to 1 to see if each flag would be set, as shown below; foreach my $headerfield qw(aa qr ad rd tc id cd){ $transporthash->{$headerfield} = 1; Show quoted text
> > } >
On a side note, since you listed the response codes, I was wondering whether you could confirm which ones a DNS server will not cache. For example, if I request "nonexistent.projectshellcode.com" I currently send back a SERVFAIL response assuming that a DNS cache would not cache failed queries. (my server doesn't need to be RFC compliant - and specifically isn't) Thanks again for your help mate, Ty On Sat, Jan 24, 2009 at 9:43 PM, Olaf M. Kolkman via RT < bug-Net-DNS@rt.cpan.org> wrote: Show quoted text
> <URL: http://rt.cpan.org/Ticket/Display.html?id=42744 > > > > I take it that you are trying to construct a reply handler. > > The ReplyHandler subroutine is passed the query name, query > class, > query type and optionally an argument containing the peerhost, > the > incoming query, and the name of the incomming socket > (sockethost). It > must return the response code and references to the answer, > authority, > and additional sections of the response. Common response > codes are: > > NOERROR No error > FORMERR Format error > SERVFAIL Server failure > NXDOMAIN Non‐existent domain (name doesn't exist) > NOTIMP Not implemented > REFUSED Query refused > > For advanced usage it may also contain a headermaks containing > an > hashref with the settings for the "aa", "ra", and "ad" header > bits. The > argument is of the form "{ ad => 1, aa => 0, ra => 1 }". > > > The argument that tweaks the bits is not a header object but a > reference to a hash containing the header values. > > Here is a code sniplet from Net::DNS::TestNS that sets the arguments > and uses the headermask, maybe that is of use. > > > > # The XML has been parsed and all info sits in the %answer db.. > # We now construct the reply handler using that. > my $reply_handler = sub { > my ($qname, $qclass, $qtype) = @_; > $qname.="." if $qname !~ /\.$/; > my ($rcode, @ans, @auth, @add); > if ( exists $answerdb{$qname}->{$qtype}){ > $rcode= $answerdb{$qname}->{$qtype}->{'rcode'}; > my $transporthash= { > 'aa' => > $answerdb{$qname}->{$qtype}-> > {'header'}->{'aa'}, > 'ra' => > $answerdb{$qname}->{$qtype}-> > {'header'}->{'ra'}, > }; > > foreach my $headerfield qw(aa qr ad rd tc id cd > qdcount ancount nscount arcount > ){ > $transporthash->{$headerfield}= > $answerdb{$qname}->{$qtype}-> > {'header'}->{$headerfield} if defined > $answerdb{$qname}->{$qtype}->{'header'}->{$headerfield} > ; > } > > print "Sleeping for " . > $answerdb{$qname}->{$qtype}->{'delay'} > . " seconds " > if $self->{verbose} && > $answerdb{$qname}->{$qtype}->{'delay'}; > > sleep ($answerdb{$qname}->{$qtype}->{'delay'}); > > if (defined($answerdb{$qname}->{$qtype}->{'raw'})){ > > $transporthash->{'raw'}=$answerdb{$qname}->{$qtype}->{'raw'}; > } > > > return ($rcode, $answerdb{$qname}->{$qtype}->{'answer'}, > $answerdb{$qname}->{$qtype}->{'authority'}, > $answerdb{$qname}->{$qtype}->{'additional'}, > $transporthash); > > } > > return ("SERVFAIL"); > }; > > > > > Hope this helps, > > --Olaf > > > On Jan 24, 2009, at 3:55 AM, Ty Miller via RT wrote: >
> > Fri Jan 23 21:55:01 2009: Request 42744 was acted upon. > > Transaction: Ticket created by tyronmiller > > Queue: Net-DNS > > Subject: Net::DNS::Header->tc(1) doesn't set Trucation flag > > Broken in: 0.63 > > Severity: Important > > Owner: Nobody > > Requestors: tyronmiller@gmail.com > > Status: new > > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > > > > > > > I am trying to send large DNS responses, which means I need to set the > > "tc" flag so that the transport changes from UDP to TCP due to > > truncated > > data. When using the following code, the header data is printed out > > with > > the "tc" flag set; however, in Wireshark the flag is still shown to be > > off and the transport does not get redirected to TCP by the requesting > > DNS server. > > > > [snip] > > $header = Net::DNS::Header->new; > > $header->aa(1); # sets aa flag in both printed output and wireshark > > $header->tc(1); # sets tc flag in printed output, but not wireshark > > $header->print; # prints both flags as being set, but tc not shown in > > wireshark > > my @response = ($rcode, \@ans, \@auth, \@add, $header); > > return @response; > > #end reply handler > > > > I am using version 0.63, and I checked the changelog for 0.64 but > > there > > was no mention of a bug fix for this issue.
> > >
Subject: Re: [rt.cpan.org #42744] Net::DNS::Header->tc(1) doesn't set Trucation flag
Date: Tue, 27 Jan 2009 11:51:16 +0100
To: bug-Net-DNS [...] rt.cpan.org
From: Olaf Kolkman <olaf [...] dacht.net>
On Jan 27, 2009, at 9:53 AM, Ty Miller via RT wrote: Show quoted text
> Queue: Net-DNS > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=42744 > > > Hi Olaf, > > Thanks so much for the quick and detailed response. > > Yes, I have implemented a ReplyHandler which works fine, except that > the > responses I am sending are larger than 512 bytes, so i'm trying to > set the > truncation bit (tc) so that the protocol falls back to TCP, which > should > allow me to send large DNS responses. > > I can see how you have used the "transporthash" in the code. Sorry > about my > misunderstanding. Originally I was doing this; however, I tried to > set the > tc bit directly in the hash ... like ... { aa => 1, tc => 1} ... which > obviously didn't work. > > I implemented the technique shown below where it sets the hash and > then > loops through the other flags (including tc); however, I am still > struggling > to get it to work. Some of the other flags seem to get set, but the > tc flag > is still not being set - as shown by wireshark. The only difference > to the > implementation that you provied was that I didn't have the > "answerdb", and > simply set the header field to 1 to see if each flag would be set, > as shown > below; > > foreach my $headerfield qw(aa qr ad rd tc id cd){ > $transporthash->{$headerfield} = 1;
>> >> } >>
> >
I have no time to dig into this shortly. Show quoted text
> On a side note, since you listed the response codes, I was wondering > whether > you could confirm which ones a DNS server will not cache. For > example, if I > request "nonexistent.projectshellcode.com" I currently send back a > SERVFAIL > response assuming that a DNS cache would not cache failed queries. (my > server doesn't need to be RFC compliant - and specifically isn't)
That is implementation specific. Some clients may 'cache' the SERVFAIL and may not return to your server for some time. One of the things you can do is send back a NXDOMAIN with a SOA RR that has a its negative caching field set to 0. But that may also not be respected. --Olaf
Download PGP.sig
application/pgp-signature 194b

Message body not shown because it is not plain text.

Subject: Re: [rt.cpan.org #42744] Net::DNS::Header->tc(1) doesn't set Trucation flag
Date: Wed, 28 Jan 2009 08:17:21 +1100
To: bug-Net-DNS [...] rt.cpan.org
From: Ty Miller <tyronmiller [...] gmail.com>
Thanks Olaf. Sorry to bug you about this. The truncation bit doesn't seem to work, and I can't find any descent examples of anyone actually getting it to work. Thanks again, Ty On Tue, Jan 27, 2009 at 9:53 PM, Olaf M. Kolkman via RT < bug-Net-DNS@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > > > > On Jan 27, 2009, at 9:53 AM, Ty Miller via RT wrote: >
> > Queue: Net-DNS > > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=42744 > > > > > Hi Olaf, > > > > Thanks so much for the quick and detailed response. > > > > Yes, I have implemented a ReplyHandler which works fine, except that > > the > > responses I am sending are larger than 512 bytes, so i'm trying to > > set the > > truncation bit (tc) so that the protocol falls back to TCP, which > > should > > allow me to send large DNS responses. > > > > I can see how you have used the "transporthash" in the code. Sorry > > about my > > misunderstanding. Originally I was doing this; however, I tried to > > set the > > tc bit directly in the hash ... like ... { aa => 1, tc => 1} ... which > > obviously didn't work. > > > > I implemented the technique shown below where it sets the hash and > > then > > loops through the other flags (including tc); however, I am still > > struggling > > to get it to work. Some of the other flags seem to get set, but the > > tc flag > > is still not being set - as shown by wireshark. The only difference > > to the > > implementation that you provied was that I didn't have the > > "answerdb", and > > simply set the header field to 1 to see if each flag would be set, > > as shown > > below; > > > > foreach my $headerfield qw(aa qr ad rd tc id cd){ > > $transporthash->{$headerfield} = 1;
> >> > >> } > >>
> > > >
> > I have no time to dig into this shortly. > >
> > On a side note, since you listed the response codes, I was wondering > > whether > > you could confirm which ones a DNS server will not cache. For > > example, if I > > request "nonexistent.projectshellcode.com" I currently send back a > > SERVFAIL > > response assuming that a DNS cache would not cache failed queries. (my > > server doesn't need to be RFC compliant - and specifically isn't)
> > > > That is implementation specific. Some clients may 'cache' the SERVFAIL > and may not return to your server for some time. > > One of the things you can do is send back a NXDOMAIN with a SOA RR > that has a its negative caching field set to 0. But that may also not > be respected. > > --Olaf > > > >
Subject: Re: [rt.cpan.org #42744] Net::DNS::Header->tc(1) doesn't set Trucation flag
Date: Fri, 03 Jul 2009 08:36:55 +0200
To: bug-Net-DNS [...] rt.cpan.org
From: Olaf Kolkman <olaf [...] dacht.net>
Ty Miller via RT wrote: Show quoted text
> Queue: Net-DNS > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > > > Thanks Olaf. Sorry to bug you about this. The truncation bit doesn't seem to > work, and I can't find any descent examples of anyone actually getting it to > work. > > Thanks again, > Ty > > > On Tue, Jan 27, 2009 at 9:53 PM, Olaf M. Kolkman via RT < > bug-Net-DNS@rt.cpan.org> wrote: > >
>> <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > >> >> >> On Jan 27, 2009, at 9:53 AM, Ty Miller via RT wrote: >> >>
>>> Queue: Net-DNS >>> Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=42744 > >>> >>> Hi Olaf, >>> >>> Thanks so much for the quick and detailed response. >>> >>> Yes, I have implemented a ReplyHandler which works fine, except that >>> the >>> responses I am sending are larger than 512 bytes, so i'm trying to >>> set the >>> truncation bit (tc) so that the protocol falls back to TCP, which >>> should >>> allow me to send large DNS responses. >>> >>> I can see how you have used the "transporthash" in the code. Sorry >>> about my >>> misunderstanding. Originally I was doing this; however, I tried to >>> set the >>> tc bit directly in the hash ... like ... { aa => 1, tc => 1} ... which >>> obviously didn't work. >>> >>> I implemented the technique shown below where it sets the hash and >>> then >>> loops through the other flags (including tc); however, I am still >>> struggling >>> to get it to work. Some of the other flags seem to get set, but the >>> tc flag >>> is still not being set - as shown by wireshark. The only difference >>> to the >>> implementation that you provied was that I didn't have the >>> "answerdb", and >>> simply set the header field to 1 to see if each flag would be set, >>> as shown >>> below; >>> >>> foreach my $headerfield qw(aa qr ad rd tc id cd){ >>> $transporthash->{$headerfield} = 1; >>>
>>>> } >>>> >>>>
>>>
>> I have no time to dig into this shortly. >> >> >>
>>> On a side note, since you listed the response codes, I was wondering >>> whether >>> you could confirm which ones a DNS server will not cache. For >>> example, if I >>> request "nonexistent.projectshellcode.com" I currently send back a >>> SERVFAIL >>> response assuming that a DNS cache would not cache failed queries. (my >>> server doesn't need to be RFC compliant - and specifically isn't) >>>
>> >> That is implementation specific. Some clients may 'cache' the SERVFAIL >> and may not return to your server for some time. >> >> One of the things you can do is send back a NXDOMAIN with a SOA RR >> that has a its negative caching field set to 0. But that may also not >> be respected. >> >> --Olaf >> >> >> >> >>
> > > > ------------------------------------------------------------------------ > > Thanks Olaf. Sorry to bug you about this. The truncation bit doesn't > seem to work, and I can't find any descent examples of anyone actually > getting it to work. > > Thanks again, > Ty > > > On Tue, Jan 27, 2009 at 9:53 PM, Olaf M. Kolkman via RT > <bug-Net-DNS@rt.cpan.org <mailto:bug-Net-DNS@rt.cpan.org>> wrote: > > <URL: https://rt.cpan.org/Ticket/Display.html?id=42744 > > > > On Jan 27, 2009, at 9:53 AM, Ty Miller via RT wrote: >
> > Queue: Net-DNS > > Ticket <URL: http://rt.cpan.org/Ticket/Display.html?id=42744 > > > > > Hi Olaf, > > > > Thanks so much for the quick and detailed response. > > > > Yes, I have implemented a ReplyHandler which works fine, except that > > the > > responses I am sending are larger than 512 bytes, so i'm trying to > > set the > > truncation bit (tc) so that the protocol falls back to TCP, which > > should > > allow me to send large DNS responses. > > > > I can see how you have used the "transporthash" in the code. Sorry > > about my > > misunderstanding. Originally I was doing this; however, I tried to > > set the > > tc bit directly in the hash ... like ... { aa => 1, tc => 1} ...
> which
> > obviously didn't work. > > > > I implemented the technique shown below where it sets the hash and > > then > > loops through the other flags (including tc); however, I am still > > struggling > > to get it to work. Some of the other flags seem to get set, but the > > tc flag > > is still not being set - as shown by wireshark. The only difference > > to the > > implementation that you provied was that I didn't have the > > "answerdb", and > > simply set the header field to 1 to see if each flag would be set, > > as shown > > below; > > > > foreach my $headerfield qw(aa qr ad rd tc id cd){ > > $transporthash->{$headerfield} = 1;
> >> > >> } > >>
> > > >
> > I have no time to dig into this shortly. > >
> > On a side note, since you listed the response codes, I was wondering > > whether > > you could confirm which ones a DNS server will not cache. For > > example, if I > > request "nonexistent.projectshellcode.com
> <http://nonexistent.projectshellcode.com>" I currently send back a
> > SERVFAIL > > response assuming that a DNS cache would not cache failed
> queries. (my
> > server doesn't need to be RFC compliant - and specifically isn't)
> > > > That is implementation specific. Some clients may 'cache' the SERVFAIL > and may not return to your server for some time. > > One of the things you can do is send back a NXDOMAIN with a SOA RR > that has a its negative caching field set to 0. But that may also not > be respected. > > --Olaf > > > >
Quick fix, that may not get into the release since truncation involves a lot of 'intelligence' (See RFC2181 about dropping by RRset etc) and therefore a special method to do the truncation may be more appropriate. In Nameserver.pm find this code fragment: if (!defined ($headermask)) { $reply->header->ra(1); $reply->header->ad(0); } else { $reply->header->aa(1) if $headermask->{'aa'}; $reply->header->ra(1) if $headermask->{'ra'}; $reply->header->ad(1) if $headermask->{'ad'}; if (defined $Net::DNS::opcodesbyname{$headermask->{'opcode'}}){ $reply->header->opcode( $headermask->{'opcode'} ); } } and add $reply->header->tc(1) if $headermask->{'tc'}; in the then-part of the if-then statement. (not tested) --Olaf
 
The Truncation code has been implemented differently than suggested, the test code was used but modified.

Fixed on the trunk as of version 835

From Chances:

 
Feature Truncation for Nameserver
    fixes rt.cpan.org #33547 and #42744
 
    TAKE CARE:
    this feature may cause unexpected behavior for your nameservers
    and can be turned off by setting Truncate to 0 during the creation
    of the nameserver. 
    my $ns = Net::DNS::Nameserver->new(
Truncate => 0,
 
    );
 
 
    Net::DNS::Packet::truncate is a new method that is called from
    within Net::DNS::Nameserver that truncates a packet according to
    the rules of RFC2181 section 9.
 
    Acknowledgement Aaron Crane for an elegant test and for
    inspiration for a direction.
 
CC: cpan [...] aaroncrane.co.uk
Subject: Re: [rt.cpan.org #33547] Net::DNS::Nameserver doesn't truncate long UDP replies [PATCH]
Date: Tue, 29 Dec 2009 22:31:21 +0000
To: Olaf Kolkman via RT <bug-Net-DNS [...] rt.cpan.org>, tyronmiller [...] gmail.com
From: tyronmiller [...] gmail.com
Hey Olaf, Thanks for your persistance with this. It will come in handy! Thanks again, Ty On , Olaf Kolkman via RT <bug-Net-DNS@rt.cpan.org> wrote: Show quoted text
Show quoted text
> The Truncation code has been implemented differently than suggested, the > test
Show quoted text
> code was used but modified.
Show quoted text
> Fixed on the trunk as of version 835
Show quoted text
> From Chances:
Show quoted text
> Feature Truncation for Nameserver fixes rt.cpan.org #33547 and #42744 TAKE
Show quoted text
> CARE: this feature may cause unexpected behavior for your nameservers and > can
Show quoted text
> be turned off by setting Truncate to 0 during the creation of the > nameserver.
Show quoted text
> my $ns = Net::DNS::Nameserver->new( Truncate => 0, );
Show quoted text
> Net::DNS::Packet::truncate is a new method that is called from within
Show quoted text
> Net::DNS::Nameserver that truncates a packet according to the rules of > RFC2181
Show quoted text
> section 9. Acknowledgement Aaron Crane for an elegant test and for > inspiration
Show quoted text
> for a direction.