in reply to Disassembling DNS Packet

Net::DNS::Packet doesn't work. It parses the header okay, but can't find the answer.
Since it parses the header, it probably getting you 80% of the way there - You should be able to subclass the part that does not work.

You did not define "does not work" - does it give you the right length ? Right number of RR's ? It is just the RR parsing that is broken ?

Have you tried to run it in debug mode to see where it breaks ?

     Syntactic sugar causes cancer of the semicolon.        --Alan Perlis

Replies are listed 'Best First'.
Re^2: Disassembling DNS Packet
by mpapet (Novice) on May 13, 2010 at 15:47 UTC
    Thanks for taking a stab at a vague question.

    You did not define "does not work"

    It does not return any RR's or the Question. It parses the UDP header. I have that with NetPacket::UDP.

    I've got a more specific question that will probably get me started in the right direction. The transaction ID is the first two bytes in the payload. The following code should return the transaction ID, but I'm not doing it right

    my $udp_packet = NetPacket::UDP->decode($A_raw_IP_Packet); my $payload = $udp_obj->{data}; #unpack "v" might return the two-bytes as an integer? my $transID = unpack(v, substr($payload,0,2); print "there's a transID of $transID \n";

    Running my script, I get

    Theres a transid 14964. In a separate terminal, dig returns an ID 7751

Re^2: Disassembling DNS Packet
by mpapet (Novice) on May 13, 2010 at 15:47 UTC
    Thanks for taking a stab at a vague question.

    You did not define "does not work"

    It does not return any RR's or the Question. It parses the UDP header. I have that with NetPacket::UDP.

    I've got a more specific question that will probably get me started in the right direction. The transaction ID is the first two bytes in the payload. The following code should return the transaction ID, but I'm not doing it right

    my $udp_packet = NetPacket::UDP->decode($A_raw_IP_Packet); my $payload = $udp_obj->{data}; #unpack "v" might return the two-bytes as an integer? my $transID = unpack(v, substr($payload,0,2)); print "there's a transID of $transID \n";

    Running my script, I get

    Theres a transid 14964. In a separate terminal, dig returns an ID 7751

      I figured the question about getting the ID from the UDP payload with everyone's help. My problem was the implementation of NetPacket::IP and then NetPacket::UDP. The following code gets the ID out of the DNS packet.

      my $ip_obj = NetPacket::IP::strip($Raw_IP_Packet); my $udp_obj = NetPacket::UDP->decode($ip_obj); if ($udp_obj->{len}) { my $payload = $udp_obj->{data}; my $transid1 = unpack('n', substr($payload,0,2)); print "The transID is $transid1 \n"; }

      My big mistake was the first line was wrong. " ...NetPacket::IP->decode($Raw_IP_packet);" This doesn't get the packet set up right. As the documentation for NetPacket::IP says, it happily parses garbage.

      Net::DNS::Packet works, but I didn't see the errors of my ways until I got the ID working. the following code works in my situation.

      use Net::DNS::Packet; use Data::Dumper; use NetPacket::UDP; use NetPacket::IP; my $ip_obj = NetPacket::IP::strip($Raw_IP_Packet); my $udp_obj = NetPacket::UDP->decode($ip_obj); if ($udp_obj->{len}) { my $payload2 = $udp_obj->{data}; my $test = Net::DNS::Packet->new(\$payload2); if ($test) { my @answer = $test->answer; print Dumper(@answer); } else { print "no Net::DNS::Packet \n";} } }

      I get a complete @answer back when doing "dig slashdot.org" in another terminal.

      A big thank you to everyone who gave me a push in the right direction despite my vague question.

      unpack "v"? Are you sure? Little-endian? For a network protocol?

        It should definitely be 'n'. "When a multi-octet quantity is transmitted[,] the most significant octet is transmitted first."

        unpack "v"? Are you sure? Little-endian? For a network protocol?

        This is where I need some help.

        my $transid = unpack('n', substr($payload,0,2));

        My script returns "Theres a transid 29754" and dig returns 43785 in a separate terminal.

      As JavaFan has said that should be 'n', not 'v'. If IDs in script and terminal are different, then how do you know that you captured the right packet? Why do you assigning decoded UDP packet to $udp_packet variable, but getting $payload from $udp_obj? Are you using strict and warnings? Could you post packet data and actual script that we could run?

      See also How do I post a question effectively?

Re^2: Disassembling DNS Packet
by Anonymous Monk on May 14, 2010 at 06:27 UTC

    Weird....

    Are you sure you are using the methods correctly. Also. Does the header question count indicate there is a question section, same for the answer section?

    e.g:

    my $packet = $res->send($data->{'name'}, $data->{'type'}, 'IN'); ok($packet, "Got an answer for $data->{name} IN $data->{type}"); is($packet->header->qdcount, 1, 'Only one question'); is($packet->header->ancount, 1, 'Got single answer'); my $question = ($packet->question)[0]; my $answer = ($packet->answer)[0];

    If you did all those things. You could consider sending a bug report via https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Net-DNS and make sure you include some sample packet data.

    --Olaf (Net::DNS maintainer)