feat: add full Zonemaster stack with Docker and Spanish UI
- Clone all 5 Zonemaster component repos (LDNS, Engine, CLI, Backend, GUI) - Dockerfile.backend: 8-stage multi-stage build LDNS→Engine→CLI→Backend - Dockerfile.gui: Astro static build served via nginx - docker-compose.yml: backend (internal) + frontend (port 5353) - nginx.conf: root redirects to /es/, /api/ proxied to backend - zonemaster-gui/config.ts: defaultLanguage set to 'es' (Spanish) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
313
zonemaster-ldns/lib/Zonemaster/LDNS/Packet.pm
Normal file
313
zonemaster-ldns/lib/Zonemaster/LDNS/Packet.pm
Normal file
@@ -0,0 +1,313 @@
|
||||
package Zonemaster::LDNS::Packet;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Zonemaster::LDNS;
|
||||
use Zonemaster::LDNS::RRList;
|
||||
|
||||
use MIME::Base64;
|
||||
|
||||
sub TO_JSON {
|
||||
my ( $self ) = @_;
|
||||
|
||||
return {
|
||||
'Zonemaster::LDNS::Packet' => {
|
||||
data => encode_base64( $self->wireformat, '' ),
|
||||
answerfrom => $self->answerfrom,
|
||||
timestamp => $self->timestamp,
|
||||
querytime => $self->querytime,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
sub data {
|
||||
my ( $self ) = @_;
|
||||
|
||||
return $self->wireformat;
|
||||
}
|
||||
|
||||
sub question_rrlist {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = sort $self->question();
|
||||
|
||||
return Zonemaster::LDNS::RRList->new( \@records );
|
||||
}
|
||||
|
||||
sub answer {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = $self->answer_unfiltered;
|
||||
|
||||
for ( my $i = $#records ; $i >= 0 ; --$i ) {
|
||||
if ( !$records[$i]->check_rd_count()
|
||||
|| ( $records[$i]->type() eq 'DNSKEY' && $records[$i]->keysize() == -1 ) )
|
||||
{
|
||||
splice @records, $i, 1;
|
||||
}
|
||||
}
|
||||
|
||||
return @records;
|
||||
}
|
||||
|
||||
sub answer_rrlist {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = sort $self->answer();
|
||||
|
||||
return Zonemaster::LDNS::RRList->new( \@records );
|
||||
}
|
||||
|
||||
sub authority {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = $self->authority_unfiltered;
|
||||
|
||||
for ( my $i = $#records ; $i >= 0 ; --$i ) {
|
||||
if ( !$records[$i]->check_rd_count() ) {
|
||||
splice @records, $i, 1;
|
||||
}
|
||||
}
|
||||
|
||||
return @records;
|
||||
}
|
||||
|
||||
sub authority_rrlist {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = sort $self->authority();
|
||||
|
||||
return Zonemaster::LDNS::RRList->new( \@records );
|
||||
}
|
||||
|
||||
sub additional {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = $self->additional_unfiltered;
|
||||
|
||||
for ( my $i = $#records ; $i >= 0 ; --$i ) {
|
||||
if ( !$records[$i]->check_rd_count() ) {
|
||||
splice @records, $i, 1;
|
||||
}
|
||||
}
|
||||
|
||||
return @records;
|
||||
}
|
||||
|
||||
sub additional_rrlist {
|
||||
my ( $self ) = @_;
|
||||
|
||||
my @records = sort $self->additional();
|
||||
|
||||
return Zonemaster::LDNS::RRList->new( \@records );
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Zonemaster::LDNS::Packet - objects representing DNS packets
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
my $p = $resolver->query('www.iis.se');
|
||||
foreach my $rr ($p->answer) {
|
||||
say $rr->string if $rr->type eq 'A';
|
||||
}
|
||||
|
||||
=head1 CLASS METHODS
|
||||
|
||||
=over
|
||||
|
||||
=item new($name, $type, $class)
|
||||
|
||||
Creates a new L<Zonemaster::LDNS::Packet> object, holding nothing but a query record for the provided triplet.
|
||||
C<$name> corresponds to the QNAME. C<$type> and C<$class> are optional, and default to A and IN respectively.
|
||||
|
||||
=item new_from_wireformat($data)
|
||||
|
||||
Creates a new L<Zonemaster::LDNS::Packet> object from the given wireformat data, if possible. Throws an exception if not.
|
||||
|
||||
=back
|
||||
|
||||
=head1 INSTANCE METHODS
|
||||
|
||||
=over
|
||||
|
||||
=item rcode([$string])
|
||||
|
||||
Returns the packet RCODE. If given an argument, tries to set the RCODE to the
|
||||
relevant value. If the given string isn't recognized as an RCODE, an exception
|
||||
will be thrown.
|
||||
|
||||
=item opcode([$string])
|
||||
|
||||
Returns the packet OPCODE. If given an argument, tries to set the OPCODE to the
|
||||
relevant value. If the given string isn't recognized as an OPCODE, an exception
|
||||
will be thrown.
|
||||
|
||||
=item id([$value])
|
||||
|
||||
Returns the packet id number. If given an argument, sets the ID value to that
|
||||
value.
|
||||
|
||||
=item qr()
|
||||
|
||||
=item aa()
|
||||
|
||||
=item tc()
|
||||
|
||||
=item rd()
|
||||
|
||||
=item cd()
|
||||
|
||||
=item ra()
|
||||
|
||||
=item ad()
|
||||
|
||||
=item do()
|
||||
|
||||
Reads and/or sets the equivalently named flags.
|
||||
|
||||
=item size()
|
||||
|
||||
Returns the length of the packet's wireformat form in octets.
|
||||
|
||||
=item edns_size()
|
||||
|
||||
Gets and/or sets the EDNS0 UDP size.
|
||||
|
||||
=item edns_rcode()
|
||||
|
||||
Gets and/or sets the EDNS0 Extended RCODE field.
|
||||
|
||||
=item ends_z()
|
||||
|
||||
Gets and/or sets the EDNS0 Z bits.
|
||||
|
||||
=item edns_data()
|
||||
|
||||
Gets and/or sets the EDNS0 RDATA. See LDNS.xs for more details.
|
||||
|
||||
=item needs_edns()
|
||||
|
||||
This method returns true if the packet has the DO flag set, an EDNS0 size set,
|
||||
and EDNS0 extended RCODE set or if the OPT pseudo-RR has one or more RDATA
|
||||
fields. It can fail to correctly flag a packet with an OPT pseudo-RR as having
|
||||
EDNS, if the pseudo-RR specifies an UDP size of zero, an extended RCODE of zero
|
||||
and the DO flag is unset. Since any UDP size less than 512 must be interpreted
|
||||
as 512, packets like that should be very rare in practice if they exist at all.
|
||||
|
||||
Note that the OPT pseudo-RR is not visible as an RR in the packet, nor is it
|
||||
included in the RR count header fields.
|
||||
|
||||
=item has_edns()
|
||||
|
||||
An alias for needs_edns().
|
||||
|
||||
=item edns_version($version)
|
||||
|
||||
Get or set the EDNS version in the packet. For incoming packets, returns 0 if
|
||||
the packet does not have an OPT pseudo-RR and 0 if it's an EDNS0 packet. It's
|
||||
thus rather pointless until such time as EDNS1 is defined.
|
||||
|
||||
=item set_edns_present
|
||||
|
||||
Set edns_present flag to true.
|
||||
|
||||
This flag can be set when creating a packet with EDNS corner cases data that
|
||||
could not be detected by need_edns/has_edns methods.
|
||||
|
||||
When set, need_edns/has_edns methods return true value.
|
||||
|
||||
=item unset_edns_present
|
||||
|
||||
Set edns_present flag to false.
|
||||
|
||||
=item querytime([$value])
|
||||
|
||||
Returns the time the query this packet is the answer to took to execute, in
|
||||
milliseconds. If given a value, sets the querytime to that value.
|
||||
|
||||
=item answerfrom($ipaddr)
|
||||
|
||||
Returns and optionally sets the IP address the packet was received from. If an attempt is made to set it to a string that cannot be parsed as an
|
||||
IPv4 or IPv6 address, an exception is thrown.
|
||||
|
||||
=item timestamp($time)
|
||||
|
||||
The time when the query was sent or received (the ldns docs don't specify), as a floating-point value on the Unix time_t scale (that is, the same
|
||||
kind of value used by L<Time::HiRes::time()>). Conversion effects between floating-point and C<struct timeval> means that the precision of the
|
||||
value is probably not reliable at the microsecond level, even if you computer's clock happen to be.
|
||||
|
||||
=item all()
|
||||
|
||||
Returns a L<Zonemaster::LDNS::RRList> object, containing the resource records from all sections except for the question section.
|
||||
|
||||
=item question()
|
||||
|
||||
Returns a list of objects representing the RRs in the question section. They will be of classes appropriate to their types, but all will have
|
||||
L<Zonemaster::LDNS::RR> as a base class.
|
||||
|
||||
=item question_rrlist()
|
||||
|
||||
Similar to L<question()>, but instead returns a single (and sorted) L<Zonemaster::LDNS::RRList> object.
|
||||
|
||||
=item answer()
|
||||
|
||||
Similar to L<answer_unfiltered()>, but ignores incomplete resource records.
|
||||
|
||||
=item answer_rrlist()
|
||||
|
||||
Similar to L<answer()>, but instead returns a single (and sorted) L<Zonemaster::LDNS::RRList> object.
|
||||
|
||||
=item answer_unfiltered()
|
||||
|
||||
Returns a list of objects representing the RRs in the answer section. They will be of classes appropriate to their types, but all will have
|
||||
L<Zonemaster::LDNS::RR> as a base class.
|
||||
|
||||
=item authority()
|
||||
|
||||
Similar to L<authority_unfiltered()>, but ignores incomplete resource records.
|
||||
|
||||
=item authority_rrlist()
|
||||
|
||||
Similar to L<authority()>, but instead returns a single (and sorted) L<Zonemaster::LDNS::RRList> object.
|
||||
|
||||
=item authority_unfiltered()
|
||||
|
||||
Returns a list of objects representing the RRs in the authority section. They will be of classes appropriate to their types, but all will have
|
||||
L<Zonemaster::LDNS::RR> as a base class.
|
||||
|
||||
=item additional()
|
||||
|
||||
Similar to L<additional_unfiltered()>, but ignores incomplete resource records.
|
||||
|
||||
=item additional_rrlist()
|
||||
|
||||
Similar to L<additional()>, but instead returns a single (and sorted) L<Zonemaster::LDNS::RRList> object.
|
||||
|
||||
=item additional_unfiltered()
|
||||
|
||||
Returns a list of objects representing the RRs in the additional section. They will be of classes appropriate to their types, but all will have
|
||||
L<Zonemaster::LDNS::RR> as a base class.
|
||||
|
||||
=item unique_push($section, $rr)
|
||||
|
||||
Push an RR object into the given section, if an identical RR isn't already present. If the section isn't one of "question", "answer", "authority"
|
||||
or "additional" an exception will be thrown. C<$rr> must be a L<Zonemaster::LDNS::RR> subclass.
|
||||
|
||||
=item string()
|
||||
|
||||
Returns a string with the packet and its contents in common presentation format.
|
||||
|
||||
=item wireformat()
|
||||
|
||||
Returns a Perl string holding the packet in wire format.
|
||||
|
||||
=item type()
|
||||
|
||||
Returns the ldns library's guess as to the content of the packet. One of the strings C<question>, C<referral>, C<answer>, C<nxdomain>, C<nodata> or C<unknown>.
|
||||
|
||||
=back
|
||||
Reference in New Issue
Block a user