Dealing with the responses is where it gets interesting.

You need a way to handle the response packet as an array of bytes/8-bit-characters. Inter alia, the name compression requires this.

You could split the response packet into an array @resp = map { ord($_) } split(//, $response) ; and proceed in a C-like fashion to process that as an array of unsigned 8-bit integers -- reconstructing 16-bit integers and character strings.

Or you can process the string containing response packet directly: using either substr($response, $p, $n) or unpack("\@$p ....", $response) -- where $p is your current "pointer" into the packet.

One way of using unpack to extract a name is to step along it and count the labels, so you can then unpack it much as you've suggested. This:

my $n = 0 ; my $s = $p ; my $l ; do { if ($l = unpack("\@$p C", $response)) { $n++ ; } ; $p += $l + 1 ; } while ($l) ;
sets $n to the number of labels, $s to the start of the name and advances $p past the name in the response packet $response. Then join('.', unpack("\@$s (C/a*)$n", $response)) will do the business. (Compressed names require a bit more code than this, of course.)

As you have found, you need to process the response piece-meal, because you cannot:

my ( ...., @labels, undef, $type, $class, ...) = unpack(".... (C/a*) +$n C n n ....") ;
So a number of unpack operations with '@' are required, each using your $p to start processing in the right place in the response.

I'd knock up a subroutine to extract a name from a given position in the current resoonse packet. You'll want it to return two things, the name and the position just after the name. Since you're new to Perl, you'll need to learn either that a subroutine can return a list (in List Context, of course), so:

($name, $p) = extract_name($response, $p) ; .... sub extract_name { my ($response, $p) = @_ ; my $extracted ... .... return ($extracted, $p) ; } ;
or that you can do "call by reference" type things:
sub extract_name { my ($response, $p) = @_ ; my $extracted ... .... $_[1] = $p ; # $_[1] is implicitly a reference to the 2nd +actual argument return $extracted ; } ;
Enjoy !


In reply to Re^2: How to create DNS packet by gone2015
in thread How to create DNS packet by deewanagan

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.