Skip Menu |

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

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

People
Owner: Nobody in particular
Requestors: felipe [...] felipegasper.com
Cc:
AdminCc:

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



Subject: background TCP query logic expects to read entire response at once
Date: Wed, 20 Mar 2019 13:06:22 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
The DNS server at 95.110.220.5 appears to send the initial 2 bytes (i.e., the length prefix) of a TCP DNS response separately from the rest of the response. You can see this behavior in action here: ----- perl -e'print "\0(\346\254\0\0\0\1\0\0\0\0\0\0\22campingmalibubeach\3com\0\0\1\0\1"' | strace -yy -s512 nc 95.110.220.5 53 ----- Relevant strace excerpt: ----- recvfrom(3<TCP:[10.215.218.116:44780->95.110.220.5:53]>, "\0\210", 8192, 0, 0x7fffcd9cd260, [0]) = 2 write(1</dev/pts/0>, "\0\210", 2�) = 2 select(4, [3<TCP:[10.215.218.116:44780->95.110.220.5:53]>], [], [], NULL) = 1 (in [3]) recvfrom(3<TCP:[10.215.218.116:44780->95.110.220.5:53]>, "\346\254\204\0\0\1\0\6\0\0\0\0\22campingmalibubeach\3com\0\0\1\0\1\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\227\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\232\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\235\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\240\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\243\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\246", 8192, 0, 0x7fffcd9cd260, [0]) = 136 ----- This behavior, however, makes the following Net::DNS::Resolver query fail because it’s expecting the full DNS packet to be ready along with the 2-byte length header: ----- strace -s1024 -yy perl -MIO::Select -MNet::DNS::Resolver -e'my $r = Net::DNS::Resolver->new(); $r->nameservers("95.110.220.5"); $r->recurse(0); $r->usevc(1); my $req = $r->bgsend("campingmalibubeach.com", "A"); 1 while !$r->bgisready($req); my $pkt = $r->bgread($req)' ----- Relevant excerpt of the strace: ----- recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, "\0\210", 2, 0, 0x7ffc92358888, [0]) = 2 recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, 0x215e690, 0, 0, 0x7ffc92358888, 0x7ffc9235887c) = -1 EAGAIN (Resource temporarily unavailable) recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, 0x215e6d0, 136, 0, 0x7ffc92358888, 0x7ffc9235887c) = -1 EAGAIN (Resource temporarily unavailable) ----- I thought maybe if I redo the loop that would fix the issue, but it doesn’t appear to; each time through the loop there’s a recvfrom() for 2 bytes, then maybe it receives the rest of the payload, but of course at that point it’s not a valid DNS packet, and the process just tight-loops indefinitely: ----- strace -s1024 -yy perl -MIO::Select -MNet::DNS::Resolver -e'my $r = Net::DNS::Resolver->new(); $r->nameservers("95.110.220.5"); $r->recurse(0); $r->usevc(1); my $req = $r->bgsend("campingmalibubeach.com", "A"); my $pkt; while (!$pkt) { 1 while !$r->bgisready($req); $pkt = $r->bgread($req) }' ----- Going by the POD for Net::DNS::Resolver, it looks like bgread() should block until the entire response is received? Thank you! -Felipe Gasper Mississauga, Ontario
Subject: Re: [rt.cpan.org #128901] AutoReply: background TCP query logic expects to read entire response at once
Date: Wed, 20 Mar 2019 16:57:23 -0400
To: bug-Net-DNS [...] rt.cpan.org
From: Felipe Gasper <felipe [...] felipegasper.com>
The following appears to fix the problem, if inserted after the can_read() call in bgbusy(): ----- # Ensure that TCP responses are complete before we indicate readiness. if ($handle->socktype() != SOCK_DGRAM) { my $buffer = q<>; # 65536 = stupidly high upper bound for length of a DNS message. recv( $handle, $buffer, 65536, Socket::MSG_PEEK() ) or do { warn "recv(MSG_PEEK): $!"; }; return 1 if length($buffer) <= 2; return 1 if length($buffer) < unpack('n', $buffer); } ----- MSG_PEEK is a POSIX-standard constant; I don’t know if it exists on Windows et al. Hope this helps--thank you! -FG Show quoted text
> On Mar 20, 2019, at 1:54 PM, Bugs in Net-DNS via RT <bug-Net-DNS@rt.cpan.org> wrote: > > > Greetings, > > This message has been automatically generated in response to the > creation of a trouble ticket regarding: > "background TCP query logic expects to read entire response at once", > a summary of which appears below. > > There is no need to reply to this message right now. Your ticket has been > assigned an ID of [rt.cpan.org #128901]. Your ticket is accessible > on the web at: > > https://rt.cpan.org/Ticket/Display.html?id=128901 > > Please include the string: > > [rt.cpan.org #128901] > > in the subject line of all future correspondence about this issue. To do so, > you may reply to this message. > > Thank you, > bug-Net-DNS@rt.cpan.org > > ------------------------------------------------------------------------- > The DNS server at 95.110.220.5 appears to send the initial 2 bytes (i.e., the length prefix) of a TCP DNS response separately from the rest of the response. > > You can see this behavior in action here: > ----- > perl -e'print "\0(\346\254\0\0\0\1\0\0\0\0\0\0\22campingmalibubeach\3com\0\0\1\0\1"' | strace -yy -s512 nc 95.110.220.5 53 > ----- > > Relevant strace excerpt: > ----- > recvfrom(3<TCP:[10.215.218.116:44780->95.110.220.5:53]>, "\0\210", 8192, 0, 0x7fffcd9cd260, [0]) = 2 > write(1</dev/pts/0>, "\0\210", 2�) = 2 > select(4, [3<TCP:[10.215.218.116:44780->95.110.220.5:53]>], [], [], NULL) = 1 (in [3]) > recvfrom(3<TCP:[10.215.218.116:44780->95.110.220.5:53]>, "\346\254\204\0\0\1\0\6\0\0\0\0\22campingmalibubeach\3com\0\0\1\0\1\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\227\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\232\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\235\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\240\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\243\300\f\0\1\0\1\0\1Q\200\0\4>\225\200\246", 8192, 0, 0x7fffcd9cd260, [0]) = 136 > ----- > > > This behavior, however, makes the following Net::DNS::Resolver query fail because it’s expecting the full DNS packet to be ready along with the 2-byte length header: > ----- > strace -s1024 -yy perl -MIO::Select -MNet::DNS::Resolver -e'my $r = Net::DNS::Resolver->new(); $r->nameservers("95.110.220.5"); $r->recurse(0); $r->usevc(1); my $req = $r->bgsend("campingmalibubeach.com", "A"); 1 while !$r->bgisready($req); my $pkt = $r->bgread($req)' > ----- > > Relevant excerpt of the strace: > ----- > recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, "\0\210", 2, 0, 0x7ffc92358888, [0]) = 2 > recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, 0x215e690, 0, 0, 0x7ffc92358888, 0x7ffc9235887c) = -1 EAGAIN (Resource temporarily unavailable) > recvfrom(3<TCP:[10.215.218.116:36500->95.110.220.5:53]>, 0x215e6d0, 136, 0, 0x7ffc92358888, 0x7ffc9235887c) = -1 EAGAIN (Resource temporarily unavailable) > ----- > > I thought maybe if I redo the loop that would fix the issue, but it doesn’t appear to; each time through the loop there’s a recvfrom() for 2 bytes, then maybe it receives the rest of the payload, but of course at that point it’s not a valid DNS packet, and the process just tight-loops indefinitely: > > ----- > strace -s1024 -yy perl -MIO::Select -MNet::DNS::Resolver -e'my $r = Net::DNS::Resolver->new(); $r->nameservers("95.110.220.5"); $r->recurse(0); $r->usevc(1); my $req = $r->bgsend("campingmalibubeach.com", "A"); my $pkt; while (!$pkt) { 1 while !$r->bgisready($req); $pkt = $r->bgread($req) }' > ----- > > Going by the POD for Net::DNS::Resolver, it looks like bgread() should block until the entire response is received? > > Thank you! > > -Felipe Gasper > Mississauga, Ontario
Resolved in Net::DNS 1.21