Net::DNS::Question - DNS question class


Net-DNS documentation Contained in the Net-DNS distribution.

Index


Code Index:

NAME

Top

Net::DNS::Question - DNS question class

SYNOPSIS

Top

use Net::DNS::Question

DESCRIPTION

Top

A Net::DNS::Question object represents a record in the question section of a DNS packet.

METHODS

Top

new

    $question = Net::DNS::Question->new("example.com", "MX", "IN");

Creates a question object from the domain, type, and class passed as arguments.

RFC4291 and RFC4632 IP address/prefix notation is supported for queries in in-addr.arpa and ip6.arpa subdomains.

parse

    ($question, $offset) = Net::DNS::Question->parse(\$data, $offset);

Parses a question section record at the specified location within a DNS packet. The first argument is a reference to the packet data. The second argument is the offset within the packet where the question record begins.

Returns a Net::DNS::Question object and the offset of the next location in the packet.

Parsing is aborted if the question object cannot be created (e.g., corrupt or insufficient data).

qname, zname

    print "qname = ", $question->qname, "\n";
    print "zname = ", $question->zname, "\n";

Returns the domain name. In dynamic update packets, this field is known as zname and refers to the zone name.

qtype, ztype

    print "qtype = ", $question->qtype, "\n";
    print "ztype = ", $question->ztype, "\n";

Returns the record type. In dymamic update packets, this field is known as ztype and refers to the zone type (must be SOA).

qclass, zclass

    print "qclass = ", $question->qclass, "\n";
    print "zclass = ", $question->zclass, "\n";

Returns the record class. In dynamic update packets, this field is known as zclass and refers to the zone's class.

print

string

    print $qr->string, "\n";

Returns a string representation of the question record.

data

    $qdata = $question->data($packet, $offset);

Returns the question record in binary format suitable for inclusion in a DNS packet.

Arguments are a Net::DNS::Packet object and the offset within that packet's data where the Net::DNS::Question record is to be stored. This information is necessary for using compressed domain names.

COPYRIGHT

Top

SEE ALSO

Top

perl(1), Net::DNS, Net::DNS::Resolver, Net::DNS::Packet, Net::DNS::Update, Net::DNS::Header, Net::DNS::RR, RFC 1035 Section 4.1.2


Net-DNS documentation Contained in the Net-DNS distribution.
package Net::DNS::Question;
#
# $Id: Question.pm 836 2009-12-30 09:41:53Z olaf $
#
use strict;
BEGIN { 
    eval { require bytes; }
} 

use vars qw($VERSION $AUTOLOAD);

use Carp;
use Net::DNS;

$VERSION = (qw$LastChangedRevision: 800$)[1];

sub new {
	my $self   = bless {}, shift;
	my $qname  = shift;
	my $qtype  = uc (shift || '');
	my $qclass = uc (shift || '');

	$qname = '' unless defined $qname;	# || ''; is NOT same!
	$qname =~ s/\.+$//o;			# strip gratuitous trailing dot

	# tolerate (possibly unknown) type and class in zone file order
	unless ( exists $Net::DNS::classesbyname{$qclass} ) {
		( $qtype, $qclass ) = ( $qclass, $qtype )
				if exists $Net::DNS::classesbyname{$qtype};
		( $qtype, $qclass ) = ( $qclass, $qtype ) if $qtype =~ /CLASS/;
	}
	unless ( exists $Net::DNS::typesbyname{$qtype} ) {
		( $qtype, $qclass ) = ( $qclass, $qtype )
				if exists $Net::DNS::typesbyname{$qclass};
		( $qtype, $qclass ) = ( $qclass, $qtype ) if $qclass =~ /TYPE/;
	}

	# if argument is an IP address, do appropriate reverse lookup
	my $reverse = _dns_addr($qname) if $qname =~ m/:|\d$/o;
	if ( $reverse ) {
		$qname = $reverse;
		$qtype ||= 'PTR';
	}

	$self->{qname}  = $qname;
	$self->{qtype}  = ( $qtype || 'A' );
	$self->{qclass} = ( $qclass || 'IN' );

	return $self;
}


sub _dns_addr {
	my $arg = shift;	# name or IP address

	# IP address must contain address characters only
	return undef if $arg =~ m#[^a-fA-F0-9:./]#o;

	# if arg looks like IPv4 address then map to in-addr.arpa space
	if ( $arg =~ m#(^|:.*:)((^|\d+\.)+\d+)(/(\d+))?$#o ) {
		my @parse = split /\./, $2;
		my $prefx = $5 || @parse<<3;
		my $last = $prefx > 24 ? 3 : ($prefx-1)>>3;
		return join '.', reverse( (@parse,(0)x3)[0 .. $last] ), 'in-addr.arpa';
	}

	# if arg looks like IPv6 address then map to ip6.arpa space
	if ( $arg =~ m#^((\w*:)+)(\w*)(/(\d+))?$#o ) {
		my @parse = split /:/, (reverse "0${1}0${3}"), 9;
		my @xpand = map{/./ ? $_ : ('0')x(9-@parse)} @parse;	# expand ::
		my $prefx = $5 || @xpand<<4;		# implicit length if unspecified
		my $hex = pack 'A4'x8, map{$_.'000'} ('0')x(8-@xpand), @xpand;
		my $len = $prefx > 124 ? 32 : ($prefx+3)>>2;
		return join '.', split(//, substr($hex,-$len) ), 'ip6.arpa';
	}

	return undef;
}


use constant PACKED_LENGTH => length pack 'n2', (0)x2;

sub parse {
	my ($class, $data, $offset) = @_;

	my ($qname, $index) = Net::DNS::Packet::dn_expand($data, $offset);
	die 'Exception: corrupt or incomplete data' unless $index;

	my $next = $index + PACKED_LENGTH;
	die 'Exception: incomplete data' if length $$data < $next;
	my ($qtype, $qclass) = unpack("\@$index n2", $$data);

	my $self = {	qname	=> $qname,
			qtype	=> Net::DNS::typesbyval($qtype),
			qclass	=> Net::DNS::classesbyval($qclass)
			};

	bless $self, $class;

	return wantarray ? ($self, $next) : $self;
}


#
# Some people have reported that Net::DNS dies because AUTOLOAD picks up
# calls to DESTROY.
#
sub DESTROY {}

sub zname  { &qname;  }
sub ztype  { &qtype;  }
sub zclass { &qclass; }


sub AUTOLOAD {
	my $self = shift;

	my $name = $AUTOLOAD;
	$name =~ s/.*://o;

	croak "$AUTOLOAD: no such method" unless exists $self->{$name};

	return $self->{$name} unless @_;

	my $value = shift;
	$value =~ s/\.+$//o if defined $value;	# strip gratuitous trailing dot
	$self->{$name} = $value;
}

sub print {	print &string, "\n"; }

sub string {
	my $self = shift;
	return "$self->{qname}.\t$self->{qclass}\t$self->{qtype}";
}

sub data {
	my ($self, $packet, $offset) = @_;

	my $data = $packet->dn_comp($self->{qname}, $offset);

	$data .= pack('n2',	Net::DNS::typesbyname(uc $self->{qtype}),
				Net::DNS::classesbyname(uc $self->{qclass})
				);
	return $data;
}


1;
__END__