Net::DNS::Packet(3)

🌸 Net::DNS::Packet(3) β€” the DNS protocol packet, explained by your resident Unix girlie πŸ’…

okay so bestie, listen. This is Net::DNS::Packet(3), from the User Contributed Perl Documentation, and it's literally the whole vibe of a DNS protocol packet in Perl. Like, if DNS wire format had a main character, this class would be her. ✨


πŸŽ€ NAME πŸŽ€

Net::DNS::Packet β€” DNS protocol packet. that's it, that's the name. short, iconic, no notes. πŸ‘‘


πŸ¦‹ SYNOPSIS πŸ¦‹

        use Net::DNS::Packet;

        $query = Net::DNS::Packet->new( 'example.com', 'MX', 'IN' );

        $reply = $resolver->send( $query );

see how clean that is? you build a query, you send it, the resolver hands you back a reply. that's the whole loop, periodt. πŸ’–


🌈 DESCRIPTION 🌈

okay so a Net::DNS::Packet object represents a DNS protocol packet. that's the entire description, and honestly? she said what she said. it's a packet. it's DNS. it's a whole object about it. 🫢


✨ METHODS ✨

πŸ’œ new

        $packet = Net::DNS::Packet->new( 'example.com' );
        $packet = Net::DNS::Packet->new( 'example.com', 'MX', 'IN' );

        $packet = Net::DNS::Packet->new();

if you pass a domain, a type, and a class, new() creates a Net::DNS::Packet object that's ready to make a DNS query for exactly that info. ngl you can skip the type and class, they just default to A and IN β€” the little black dress of DNS defaults. πŸ’…

and if you call it with an empty argument list, new() just creates an empty packet. a blank canvas. a fresh face. πŸŽ€


πŸ”₯ decode

        $packet = Net::DNS::Packet->decode( \$data );
        $packet = Net::DNS::Packet->decode( \$data, 1 );        # debug
        $packet = Net::DNS::Packet->new( \$data ... );

so this one creates a new packet object by decoding the DNS packet data inside the scalar your first argument references. the optional second boolean argument turns on debugging output β€” think of it as the packet telling you its whole life story while it parses. πŸ‘€

Returns undef if it can't create a packet object. so like, check your returns, bestie. 😭

decoding errors β€” including data corruption and truncation β€” get collected in the $@ ($EVAL_ERROR) variable. yes, the classic Perl error variable. she's still here, still doing her job. πŸ’€

        ( $packet, $length ) = Net::DNS::Packet->decode( \$data );

if you call it in array context, you get back a packet object and the number of octets successfully decoded. very generous of her honestly.

⚠️ real talk: the number of RRs in each section of the packet may differ from the corresponding header value if the data has been truncated or corrupted during transmission. so don't go trusting the header count blindly, ok?

🌸 encode

        $data = $packet->encode;
        $data = $packet->encode( $size );

returns the packet data in binary format, all ready to be sent as a query or update request to a nameserver. it's giving "ready to ship." πŸ“¦

truncation may be specified using a non-zero optional size argument. cute little knob, use it wisely. ✨


        $header = $packet->header;

constructor method that returns a Net::DNS::Header object representing the header section of the packet. she's the preamble. the table of contents. the header of the headers, if you will. πŸ’«


πŸ“ edns

        $version = $packet->edns->version;
        $UDPsize = $packet->edns->size;

auxiliary function that gives you access to the EDNS protocol extension OPT RR. you know, the extension to DNS that says "hey, I can handle bigger things than the original spec assumed." obsessed. πŸ¦‹


🌟 reply

        $reply = $query->reply( $UDPmax );

constructor method that returns a brand new reply packet. ✨

the optional UDPsize argument is the maximum UDP packet size that the local network stack can reassemble, and it gets advertised in response to an EDNS query. so like, it's how you tell them how much you can hold. respectfully. πŸ’…


πŸ‘‘ question, zone

        @question = $packet->question;

returns a list of Net::DNS::Question objects representing the question section of the packet. the "what even are we asking" section. the plot. 🎬

in dynamic update packets, this section is known as zone() and specifies the DNS zone to be updated. same girl, different name. iykyk. πŸ’–


🌺 answer, pre, prerequisite

        @answer = $packet->answer;

returns a list of Net::DNS::RR objects representing the answer section of the packet. the payoff. the moment. the "here's your A record" reveal. 🎁

in dynamic update packets, this section is known as pre() or prerequisite() and specifies the RRs or RRsets which must or must not preexist. very "prove yourself before I let you in" energy, honestly. πŸ™ˆ


πŸ’ authority, update

        @authority = $packet->authority;

returns a list of Net::DNS::RR objects representing the authority section of the packet. she's not the answer but she definitely knows who is. πŸ’β€β™€οΈ

in dynamic update packets, this section is known as update() and specifies the RRs or RRsets to be added or deleted. so like, the edits. the diff. the commit. πŸ”₯


🦒 additional

        @additional = $packet->additional;

returns a list of Net::DNS::RR objects representing the additional section of the packet. the bonus content. the extra fries. the "while we're here" zone. 🍟


πŸŽ€ print

        $packet->print;

prints the entire packet to the currently selected output filehandle using the master file format mandated by RFC1035. yes, RFC1035, the founding mother herself. no cap. πŸ“œ


⭐ string

        print $packet->string;

returns a string representation of the packet. so like, the packet but text-shaped. perfect for putting it in your print statements and pretending you're debugging. 😌


🫢 from

        print "packet received from ", $packet->from, "\n";

returns the IP address from which this packet was received. BUT β€” and this is the important part β€” this method will return undef for user-created packets. she only knows where she came from if she actually came from somewhere. 😭


🌼 size

        print "packet size: ", $packet->size, " octets\n";

returns the size of the packet in octets as it was received from a nameserver. same deal as above though: this method will return undef for user-created packets β€” use length($packet->data) instead. like, do the math yourself if you made the thing, bestie. πŸ’€


πŸ‡ push

        $ancount = $packet->push( prereq => $rr );
        $nscount = $packet->push( update => $rr );
        $arcount = $packet->push( additional => $rr );

        $nscount = $packet->push( update => $rr1, $rr2, $rr3 );
        $nscount = $packet->push( update => @rr );

adds RRs to the section of the packet you asked for. 🎯

returns the number of resource records in that section.

and here's a cute shortcut: section names may be abbreviated to the first three characters. so pre, upd, add β€” you get it. minimal effort, maximal slay. πŸ’…


πŸ¦„ unique_push

        $ancount = $packet->unique_push( prereq => $rr );
        $nscount = $packet->unique_push( update => $rr );
        $arcount = $packet->unique_push( additional => $rr );

        $nscount = $packet->unique_push( update => $rr1, $rr2, $rr3 );
        $nscount = $packet->unique_push( update => @rr );

same as push but with ✨standards✨ β€” it adds RRs to the specified section of the packet provided that the RRs are not already present in the same section. she does a vibe check first. no duplicates allowed, we don't do that here. 🚫

returns the number of resource records in the specified section.

section names may be abbreviated to the first three characters, same as always. πŸŽ€


πŸ•ŠοΈ pop

        my $rr = $packet->pop( 'pre' );
        my $rr = $packet->pop( 'update' );
        my $rr = $packet->pop( 'additional' );

removes a single RR from the specified section of the packet. one at a time. she's not dramatic about it, she just takes one. πŸ’…


πŸ” sign_tsig

        $query = Net::DNS::Packet->new( 'www.example.com', 'A' );

        $query->sign_tsig(
                $keyfile,
                fudge => 60
                );

        $reply = $res->send( $query );

        $reply->verify( $query ) || die $reply->verifyerr;

attaches a TSIG resource record object, which will be used to sign the packet (see RFC 2845). cryptographic handshake but make it fashion. πŸ”

the TSIG record can be customised by optional additional arguments to sign_tsig() or by calling the appropriate Net::DNS::RR::TSIG methods. your choice, bestie. 🫢

if you want to create a TSIG record using a non-standard algorithm, you'll have to create it yourself. in all cases, the TSIG name must uniquely identify the key shared between the parties, and the algorithm name must identify the signing function to be used with the specified key. no ambiguity allowed, that's literally the whole point. 🎯

        $tsig = Net::DNS::RR->new(
                name            => 'tsig.example',
                type            => 'TSIG',
                algorithm       => 'custom-algorithm',
                key             => '<base64 key text>',
                sig_function    => sub {
                                          my ($key, $data) = @_;
                                                ...
                                        }
                );

        $query->sign_tsig( $tsig );

the response to an inbound request is signed by presenting the request in place of the key parameter. so the request is the key, conceptually. cute. πŸ’«

        $response = $request->reply;
        $response->sign_tsig( $request, @options );

multi-packet transactions are signed by chaining the sign_tsig() calls together like this:

        $opaque = $packet1->sign_tsig( 'Kexample.+165+13281.private' );
        $opaque = $packet2->sign_tsig( $opaque );
        $opaque = $packet3->sign_tsig( $opaque );
🚫 so about those opaque intermediate object references returned during multi-packet signing: they are not intended to be accessed by the end-user application. Any such access is expressly forbidden. like, hands off. do not touch. i'm serious. πŸ’€
⚠️ also note: a TSIG record is added to every packet; this implementation does not support the suppressed signature scheme described in RFC2845. so don't go looking for it, it's not here. πŸ™ˆ

πŸ›‘οΈ verify and verifyerr

        $reply->verify($query) || die $reply->verifyerr;

verify the TSIG signature of a reply to the corresponding query. the "did you actually mean that" check. βœ…

        $opaque  = $packet1->verify( $query ) || die $packet1->verifyerr;
        $opaque  = $packet2->verify( $opaque );
        $verifed = $packet3->verify( $opaque ) || die $packet3->verifyerr;

verify the TSIG signature of a multi-packet reply to the corresponding query. (yes, $verifed is spelled like that in the original β€” we keep it exactly as written, no edits, no notes. πŸ’€)

the opaque intermediate object references returned by verify() at each stage will be undefined (Boolean false) if verification fails. testing at every stage is not necessary β€” which, heads up, produces a BADSIG error on the final packet in the absence of more specific information. so like, you can skip the middle checks, but then the error you get is less specific. your call. 😭

🚫 and access to the objects themselves, if they exist, is expressly forbidden. again. hands off. βœ‹

πŸŒ™ sign_sig0

SIG0 support is provided through the Net::DNS::RR::SIG class. the requisite cryptographic components are not integrated into Net::DNS but reside in the Net::DNS::SEC distribution available from CPAN. so it's a separate install, babe. πŸ’…

        $update = Net::DNS::Update->new('example.com');
        $update->push( update => rr_add('foo.example.com A 10.1.2.3'));
        $update->sign_sig0('Kexample.com+003+25317.private');
⚠️ execution will be terminated if Net::DNS::SEC is not available. like, full stop, the program is done. so install your deps first, i am begging. 😭

πŸ” verify SIG0

        $packet->verify( $keyrr )               || die $packet->verifyerr;
        $packet->verify( [$keyrr, ...] )        || die $packet->verifyerr;

verify a SIG0 packet signature against one or more specified KEY RRs. one key or a whole list of them, she's flexible. πŸ—οΈ


πŸ¦‹ sigrr

        $sigrr = $packet->sigrr() || die 'unsigned packet';

the sigrr method returns the signature RR from a signed packet, or undef if the signature is absent. and if it's absent, well β€” die 'unsigned packet' is right there waiting for you. rude but fair. πŸ’€


🎈 truncate

the truncate method takes a maximum length as argument and then tries to truncate the packet and set the TC bit according to the rules of RFC2181 Section 9. she's doing her best to fit into the small UDP envelope. πŸŽ€

the smallest length limit that is honoured is 512 octets. anything smaller, she's not doing it. πŸ’…

Copyright (c)1997-2000 Michael Fuhr.

Portions Copyright (c)2002-2004 Chris Reinhardt.

Portions Copyright (c)2002-2009 Olaf Kolkman

Portions Copyright (c)2007-2019 Dick Franks

All rights reserved.


πŸ“œ LICENSE πŸ“œ

Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the original copyright notices appear in all copies and that both copyright notice and this permission notice appear in supporting documentation, and that the name of the author not be used in advertising or publicity pertaining to distribution of the software without specific prior written permission.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


bestie that's the whole first part β€” more incoming, don't go anywhere πŸ’œ

πŸ”— SEE ALSO πŸ”—

okay bestie, you made it to the end, and now it's time for the reading list πŸ“šβœ¨ β€” every single one of these is a real thing in the original page, so go look at them, i'm literally begging 🫢

  • perl β€” yes, the whole language, the mothership, the reason any of this exists πŸ’œ
  • Net::DNS β€” the big one, the main character herself πŸ‘‘ start here if you're lost
  • Net::DNS::Header β€” the header bits, its own whole module, go read it πŸŽ€
  • Net::DNS::Question β€” the question section, yes it gets its own module too ✨
  • Net::DNS::RR β€” resource records, the general one, the icon πŸ’…
  • Net::DNS::RR::TSIG β€” the TSIG flavour of RR, off doing its own thing πŸ”₯
  • RFC1035(4.1) β€” the classic, section 4.1 specifically, the OG text fr fr ⭐ at https://iana.org/go/rfc1035#section-4.1
  • RFC2136 β€” another one, at section 2 specifically 🌸 at https://iana.org/go/rfc2136#section-2
  • RFC8490 β€” just the whole thing, no section, read it all bestie 🌈 at https://iana.org/go/rfc8490
  • RFC8945 β€” same deal, the whole document, no skimming πŸ™ˆ at https://iana.org/go/rfc8945
lowkey the RFCs are the lore drops πŸ”₯ they are long but they are the source, no cap. the section numbers above are exact, so don't go wandering β€” RFC1035(4.1) and RFC2136 section 2 are pointed at specific spots for a reason πŸ’€

and that's the whole page, bestie!! πŸŽ‰ you literally read the entire Net::DNS::Packet(3) manpage, i'm so proud πŸ˜­πŸ’– this was generated from perl v5.42.0, dated 2026-09-02, and the page you just finished is Net::DNS::Packet(3) β€” go forth and packet-ify your life, slay, periodt πŸ¦‹βœ¨πŸ’…

πŸ“¦ where this page comes from