[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


To: dnssec@cafax.se
From: Olaf Kolkman <olaf@ripe.net>
Date: Mon, 23 Apr 2001 14:29:12 +0200
Sender: owner-dnssec@cafax.se
Subject: Net::DNS perl extent-ions



Dear DNSSEC enthusiasts and Perl mongers among you,

I've been playing with Net::DNS and build in some DNSSEC material.


I have added the NXT, SIG and KEY object for dnssec where SIG has a
verify method to verify against a public key and a RRset. Verification
for both RSA and DSA keys is possible (algorithms 1 and 3). Small
modifications where needed in RR.pm and some RR/*pm objects to be able
to successfully verify RR with labels in the RDATA.

Besides this I have created an OPT RR for EDNS support. This also
needed a few additional 'if-conditions' in the Resolver object. EDNS
support is needed to indicate DNSSEC support to a bind 9.1.1 server
and to not get truncated packages. (RFC2671 and
draft-ietf-dnsext-dnssec-okbit-01.txt)

I have created a patch against the 0.19 version and that patch and the
link to the 0.19 version is included below.

Some notes:

Use Perl 5.6.0.

You will need to install Crypt::RSA, Crypt::DSA and MIME::Base64 from
CPAN. The Crypt::RSA and Crypt::DSA packages depend on other modules
as well and may not directly install from CPAN because of failing make
test (on my FreeBSD system the Random package failed to install
because it used /dev/random instead of /dev/urandom)

Disclaimer: The patch is really hot from the press and could do
(should do) with more testing and code review (pre-beta :-).  I'm not
an authority on the Net::DNS package and I might have missed some
interactions. (e.g. Version 0.19 includes a Nameserver object I have
not tested my additions against that). The reason for posting this is
to get some feed-back, reduce the change of multiple effort and to see
what people think.

My Motivation: I wrote the extensions to end up with the sigrr->verify
method. Which will verify a signature over a RRset with a public
key. Look at perldoc Net::DNS::RR::SIG for details. Using these
modules I want to build our Registry and implement key-rollovers.


There are two demo scripts included. One to just query and verify, the
other will walk a zone using the NXT record and verify all received
records. They are called demo/QueryVerify.pl and
demo/NXTzonewalkVerify.pl respectively. These script run agains our
test dnssec setup. Don;t count on this infrastructure being there for
longer then a few weeks :-).

I welcome bug reports and patches. 


--Olaf

P.S I have mailed Mike Fuhr, the author of the original module to ask
him to include the extensions but have not yet gotten any response (He
might be on holiday).


-----------------------------------------------------
  Olaf M. Kolkman      |  RIPE NCC 
     -----------       |      ---------------	   
  RIPE NCC             |  Phone:   +31 20 535 4444
  Singel 258           |  Fax:     +31 20 535 4445
  1016 AB Amsterdam    |  http://www.ripe.net
  The Netherlands      |  OKolkman@ripe.net       
 



Here comes the patch against Net::DNS version 0.19  
http://www.fuhr.org/~mfuhr/perldns/Net-DNS-current.tar.gz:

diff -B -u --recursive --new-file Net-DNS-0.19/Makefile.PL Net-DNS-0.19.patched/Makefile.PL
--- Net-DNS-0.19/Makefile.PL	Sun Nov 19 06:49:04 2000
+++ Net-DNS-0.19.patched/Makefile.PL	Mon Apr 23 13:13:51 2001
@@ -24,5 +24,7 @@
 			    MIME::Base64     => 2.11,
 			    Digest::MD5      => 2.12,
 			    Digest::HMAC_MD5 => 1.00,
+			    Crypt::RSA => 1.36,
+			    Crypt::DSA => 0.3,
 			  },
 );
diff -B -u --recursive --new-file Net-DNS-0.19/demo/NXTzonewalkVerify.pl Net-DNS-0.19.patched/demo/NXTzonewalkVerify.pl
--- Net-DNS-0.19/demo/NXTzonewalkVerify.pl	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/demo/NXTzonewalkVerify.pl	Mon Apr 23 13:04:59 2001
@@ -0,0 +1,101 @@
+#!/usr/bin/perl -w -I./
+use strict;
+
+
+
+use Net::DNS;
+use Carp;
+
+my $res = new Net::DNS::Resolver;
+
+my @datarrset;
+my ($keyrr,$sigrr);
+
+my $NS="193.0.0.202";
+$res->debug(0);
+$res->nameservers($NS);
+$res->udppacketsize(2048);
+$res->dnssec(1);
+$res->retrans(10);
+$res->cdflag(0);
+print $res->string;
+
+
+
+# start with the NXT record in the APEX of a ZONE 
+
+my $NXTQUERY="";
+my $ORGQUERY="ripencc.dnssec.nl.nl";
+my $CURQUERY=$ORGQUERY;
+
+
+
+while ( ($NXTQUERY eq "") || ($CURQUERY ne $ORGQUERY) ){
+    my @QTYPE=("NXT");
+    my @NEWQTYPE=("NXT");
+
+    while  ( $QTYPE[0] eq "NXT") {
+	@QTYPE=@NEWQTYPE;
+	for (my $j=0 ;$j < @QTYPE ; $j++){
+	    sleep 1;
+	    my $query = $res->search($CURQUERY,$QTYPE[$j]);
+	    if ($query) {
+		foreach  my $rr ($query->answer) {
+		    my $i=0;
+		    if ( $rr->type eq $QTYPE[$j] ){
+			$datarrset[$i] =  new Net::DNS::RR($rr->string);
+			print "\nFound DATARR[",$i,"]:\t", $datarrset[$i]->string, "\n";
+		        $i++;
+		    }
+		    if ( $rr->type eq "NXT" ){
+			my $typelist=$rr->{"typelist"};
+			$typelist =~ s/SIG|NXT|KEY//g;
+			$typelist =~ s/^\s*//g;   
+			@NEWQTYPE=split /\s+/, $typelist;
+			$NXTQUERY=$rr->{"nxtdname"};
+		    }
+		    
+		    if ( $rr->type eq "SIG" && $rr->typecovered eq $QTYPE[$j] ){
+			$sigrr =  new Net::DNS::RR($rr->string);
+#			print "\nFound SIG:\t", $sigrr->string, "\n";
+		    }
+		}
+		foreach  my $rr ($query->additional) {
+		    # check on label and keytag
+		    if ( $rr->type eq "KEY" && 
+			 $rr->name eq $sigrr->signame ) #	$rr->keytag == $sigrr->keytag ){
+		    {
+			$keyrr =  new Net::DNS::RR($rr->string);
+#			print "\nFound KEY:\t", $keyrr->string, "\n";
+		    }
+		    
+		}
+	    }
+	    if ( ! $keyrr ){
+		croak "No KEYRR found";
+	    }
+	    
+	    if ( ! $sigrr ){
+		croak "No SIGRR found";
+	    }
+	    
+	    if ( ! @datarrset ){
+		croak "No Answer found";
+	    }
+	    
+	    print "\n__________________________________________________";
+	    print "\nQUERY:  $CURQUERY . $QTYPE[$j] \n";
+	    
+	    if( $sigrr->verify(\@datarrset, $keyrr)){
+		print "\n--------------VERIFIED------------\n";
+	    }else{
+		print "\nNOT Verified" . $sigrr->vrfyerrstr ."\n\n";
+	    }
+
+	    $CURQUERY=$NXTQUERY;
+	}
+    }
+}
+
+    
+
diff -B -u --recursive --new-file Net-DNS-0.19/demo/QueryVerify.pl Net-DNS-0.19.patched/demo/QueryVerify.pl
--- Net-DNS-0.19/demo/QueryVerify.pl	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/demo/QueryVerify.pl	Mon Apr 23 13:05:03 2001
@@ -0,0 +1,79 @@
+#!/usr/bin/perl -w -I./
+use strict;
+
+
+
+use Net::DNS;
+use Carp;
+
+my $res = new Net::DNS::Resolver;
+
+
+
+
+
+my @datarrset;
+my ($keyrr,$sigrr);
+
+my $QUERY="x50.ripencc.dnssec.nl.nl";
+my $QTYPE="A";
+
+my $QUERY="dacht.net";
+my $QTYPE="NXT";
+my $NS="193.0.0.202";
+
+$res->debug(1);
+$res->nameservers($NS);
+$res->udppacketsize(2048);
+$res->dnssec(1);
+$res->retrans(10);
+$res->cdflag(0);
+print $res->string;
+my $i=0;
+my $query = $res->search($QUERY,$QTYPE);
+if ($query) {
+    foreach  my $rr ($query->answer) {
+	print "\n\nLooking at:\t",$rr->string;
+	if ( $rr->type eq $QTYPE ){
+	    $datarrset[$i] =  new Net::DNS::RR($rr->string);
+	    print "\nQuery:\t", $rr->string, "\n";
+	    print "\nFound DATARR[",$i,"]:\t", $datarrset[$i]->string, "\n";
+	    $i++;
+	}
+	if ( $rr->type eq "SIG" && $rr->typecovered eq $QTYPE ){
+	    $sigrr =  new Net::DNS::RR($rr->string);
+	    print "\nFound SIG:\t", $sigrr->string, "\n";
+	}
+    }
+       foreach  my $rr ($query->additional) {
+	# check on label and keytag
+	if ( $rr->type eq "KEY" && 
+	$rr->name eq $sigrr->signame ) #	$rr->keytag == $sigrr->keytag ){
+	{
+	    $keyrr =  new Net::DNS::RR($rr->string);
+	    print "\nFound KEY:\t", $keyrr->string, "\n";
+	}
+	
+    }
+}
+if ( ! $keyrr ){
+    croak "No KEYRR found";
+}
+
+if ( ! $sigrr ){
+    croak "No SIGRR found";
+}
+
+if ( ! @datarrset ){
+    croak "No Answer found";
+}
+
+print "__________________________________________________";
+
+ $sigrr->verify(\@datarrset, $keyrr) || croak $sigrr->vrfyerrstr;
+print "\n\nVERIFIED !!!!\n\n";
+print $sigrr->vrfyerrstr;
+0;
+
+
+
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Header.pm Net-DNS-0.19.patched/lib/Net/DNS/Header.pm
--- Net-DNS-0.19/lib/Net/DNS/Header.pm	Sun Nov 19 06:54:35 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/Header.pm	Mon Apr 23 13:04:59 2001
@@ -5,7 +5,9 @@
 
 use Net::DNS;
 
-# $Id: Header.pm,v 1.8 2000/11/19 05:53:56 mfuhr Exp mfuhr $
+
+# $Id: Header.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 $VERSION = $Net::DNS::VERSION;
 
 =head1 NAME
@@ -59,6 +61,8 @@
 			"tc"		=> ($a[1] >> 1) & 0x1,
 			"rd"		=> $a[1] & 0x1,
 			"ra"		=> ($a[2] >> 7) & 0x1,
+			"ad"		=> ($a[2] >> 5) & 0x1,
+			"cd"		=> ($a[2] >> 4) & 0x1,
 			"rcode"		=> $a[2] & 0xf,
 			"qdcount"	=> $a[3],
 			"ancount"	=> $a[4],
@@ -66,7 +70,7 @@
 			"arcount"	=> $a[6],
 		);
 	}
-	else {
+	else { 
 		%self = (
 			"id"		=> Net::DNS::Resolver::nextid(),
 			"qr"		=> 0,
@@ -75,6 +79,8 @@
 			"tc"		=> 0,
 			"rd"		=> 1,
 			"ra"		=> 0,
+			"ad"		=> 0,
+			"cd"		=> 0,  
 			"rcode"		=> 0,
 			"qdcount"	=> 1,
 			"ancount"	=> 0,
@@ -142,6 +148,8 @@
 		           "rd = $self->{rd}\n";
 
 		$retval .= ";; ra = $self->{ra}    " .
+		           "ad = $self->{ad}    "         .
+		           "cd = $self->{cd}    "         .
 		           "rcode  = $self->{rcode}\n";
 
 		$retval .= ";; qdcount = $self->{qdcount}  " .
@@ -195,6 +203,14 @@
 
 Gets or sets the recursion desired flag.
 
+
+=head2 rd
+
+    print "checking was ", $header->cd ? "not" : "", "desired\n";
+    $header->rd(0);
+
+Gets or sets the checking disabled flag.
+
 =head2 ra
 
     print "recursion is ", $header->ra ? "" : "not ", "available\n";
@@ -285,6 +301,7 @@
 	          | $self->{"rd"};
 
 	my $byte3 = ($self->{"ra"} << 7)
+                  | ($self->{"cd"} << 4)
 	          | $rcode;
 
 	return pack("n C2 n4", $self->{"id"},
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Nameserver.pm Net-DNS-0.19.patched/lib/Net/DNS/Nameserver.pm
--- Net-DNS-0.19/lib/Net/DNS/Nameserver.pm	Tue Dec 12 18:18:13 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/Nameserver.pm	Mon Apr 23 13:05:00 2001
@@ -1,5 +1,5 @@
 package Net::DNS::Nameserver;
-# $Id: Nameserver.pm,v 1.1 2000/12/12 17:18:00 mfuhr Exp mfuhr $
+# $Id: Nameserver.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
 
 use Net::DNS;
 use IO::Socket;
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Packet.pm Net-DNS-0.19.patched/lib/Net/DNS/Packet.pm
--- Net-DNS-0.19/lib/Net/DNS/Packet.pm	Wed Feb  7 06:14:01 2001
+++ Net-DNS-0.19.patched/lib/Net/DNS/Packet.pm	Mon Apr 23 13:05:00 2001
@@ -12,7 +12,9 @@
 use Net::DNS::Question;
 use Net::DNS::RR;
 
-# $Id: Packet.pm,v 1.13 2001/02/07 05:13:48 mfuhr Exp mfuhr $
+
+# $Id: Packet.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 $VERSION = $Net::DNS::VERSION;
 
 =head1 NAME
@@ -53,7 +55,7 @@
 packet object is undefined (i.e., couldn't be created).
 
 Returns B<undef> if unable to create a packet object (e.g., if
-the packet data is truncated).
+the packet data is truncated).'
 
 =cut
 
@@ -256,6 +258,9 @@
 	#----------------------------------------------------------------------
 	# Get the data for each section in the packet.
 	#----------------------------------------------------------------------
+	# Note that EDNS OPT RR data should inly be appended toi the additional
+        # section of the packet. Packet is dropped silently if is tried to
+	# have it appended to one of the other section
 
 	my $data = $self->{"header"}->data;
 
@@ -651,7 +656,7 @@
 Returns B<(undef, undef)> if the domain name couldn't be expanded.
 
 =cut
-
+# '
 sub dn_expand {
 	my ($packet, $offset) = @_;
 	my %seen;
@@ -832,8 +837,13 @@
 		if length($$data) < ($offset + &Net::DNS::RRFIXEDSZ);
 
 	my ($type, $class, $ttl, $rdlength) = unpack("\@$offset n2 N n", $$data);
+
 	$type  = $Net::DNS::typesbyval{$type}    || $type;
-	$class = $Net::DNS::classesbyval{$class} || $class;
+	# Special case for OPT RR where CLASS should be interperted as 16 bit 
+	# unsigned 2671 sec 4.3
+	if ($type ne "OPT"){
+	    $class = $Net::DNS::classesbyval{$class} || $class;
+	} #else just keep at its numerical value
 
 	$offset += &Net::DNS::RRFIXEDSZ;
 
@@ -856,9 +866,12 @@
 
 =head1 COPYRIGHT
 
-Copyright (c) 1997-2000 Michael Fuhr.  All rights reserved.  This
-program is free software; you can redistribute it and/or modify it
-under the same terms as Perl itself. 
+Copyright (c) 1997 Michael Fuhr.  All rights reserved.  This program is free
+software; you can redistribute it and/or modify it under the same terms as
+Perl itself. 
+
+
+DNSSEC/EDNS0 functionality courtesy of Olaf M. Kolkman, RIPE NCC.
 
 =head1 SEE ALSO
 
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Question.pm Net-DNS-0.19.patched/lib/Net/DNS/Question.pm
--- Net-DNS-0.19/lib/Net/DNS/Question.pm	Wed Feb  7 06:14:34 2001
+++ Net-DNS-0.19.patched/lib/Net/DNS/Question.pm	Mon Apr 23 13:05:00 2001
@@ -6,7 +6,8 @@
 use Carp;
 use Net::DNS;
 
-# $Id: Question.pm,v 1.7 2001/02/07 05:14:27 mfuhr Exp mfuhr $
+# $Id: Question.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 $VERSION = $Net::DNS::VERSION;
 
 =head1 NAME
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/A.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/A.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/A.pm	Sun Nov 19 07:02:44 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/A.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::A;
 
-# $Id: A.pm,v 1.5 2000/11/19 06:02:34 mfuhr Exp mfuhr $
+
+# $Id: A.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/AAAA.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/AAAA.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/AAAA.pm	Sun Nov 19 07:02:57 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/AAAA.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::AAAA;
 
-# $Id: AAAA.pm,v 1.5 2000/11/19 06:02:47 mfuhr Exp mfuhr $
+
+# $Id: AAAA.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/AFSDB.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/AFSDB.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/AFSDB.pm	Sun Nov 19 07:03:09 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/AFSDB.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::AFSDB;
 
-# $Id: AFSDB.pm,v 1.5 2000/11/19 06:03:01 mfuhr Exp mfuhr $
+
+# $Id: AFSDB.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -56,6 +58,20 @@
 
 	return $rdata;
 }
+
+
+
+sub _canonicalRdata {
+    # rdata contains a compressed domainname... we should not have that.
+	my ($self) = @_;
+	my $rdata;
+	if (exists $self->{"subtype"}) {
+	    $rdata .= pack("n", $self->{"subtype"});
+	    $rdata .=  $self->_name2wire($self->{"hostname"});
+	}
+	return $rdata;
+}
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/CNAME.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/CNAME.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/CNAME.pm	Sun Nov 19 07:03:27 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/CNAME.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::CNAME;
 
-# $Id: CNAME.pm,v 1.5 2000/11/19 06:03:20 mfuhr Exp mfuhr $
+
+# $Id: CNAME.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -49,6 +51,17 @@
 
 	return $rdata;
 }
+
+
+sub _canonicalRdata {
+    # rdata contains a compressed domainname... we should not have that.
+	my ($self) = @_;
+	my $rdata;
+	$rdata=$self->_name2wire($self->{"cname"});
+	return $rdata;
+}
+
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/EID.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/EID.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/EID.pm	Sun Nov 19 07:03:41 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/EID.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::EID;
 
-# $Id: EID.pm,v 1.2 2000/11/19 06:03:34 mfuhr Exp mfuhr $
+
+# $Id: EID.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/HINFO.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/HINFO.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/HINFO.pm	Sun Nov 19 07:03:55 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/HINFO.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::HINFO;
 
-# $Id: HINFO.pm,v 1.6 2000/11/19 06:03:45 mfuhr Exp mfuhr $
+# $Id: HINFO.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/ISDN.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/ISDN.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/ISDN.pm	Sun Nov 19 07:04:09 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/ISDN.pm	Mon Apr 23 13:05:00 2001
@@ -1,6 +1,8 @@
 package Net::DNS::RR::ISDN;
 
-# $Id: ISDN.pm,v 1.7 2000/11/19 06:04:02 mfuhr Exp mfuhr $
+# $Id: ISDN.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/KEY.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/KEY.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/KEY.pm	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/KEY.pm	Mon Apr 23 13:05:01 2001
@@ -0,0 +1,235 @@
+package Net::DNS::RR::KEY;
+
+# $Id: KEY.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
+
+use strict;
+use vars qw(@ISA);
+
+use Socket;
+use Net::DNS;
+use MIME::Base64;
+use Carp;
+
+@ISA = qw(Net::DNS::RR);
+
+sub new {
+    my ($class, $self, $data, $offset) = @_;
+    if ($self->{"rdlength"} > 0) {
+	
+	my $offsettoprot=$offset+2;
+	my $offsettoalg=$offset+3;
+	my $offsettokey=$offset+4;
+	
+	$self->{"flags"}=unpack("n",substr($$data,$offset,2));
+	$self->{"protocol"}=unpack("C",substr($$data,$offsettoprot,1));
+	$self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1));
+	my $keymaterial=substr($$data,$offsettokey,$self->{"rdlength"}-4);
+	$self->{"keybin"}=($keymaterial);
+	$self->{"key"}= encode_base64($keymaterial);
+	
+	setkeytag($self);	
+    }
+    return bless $self, $class;
+}
+
+
+
+
+
+sub new_from_string {
+	my ($class, $self, $string) = @_;
+
+
+	if ($string) {
+		$string =~ tr/()//d;
+		$string =~ s/;.*$//mg;
+		my ($flags, $protocol, $algorithm) = 
+		    $string =~ /^\s*(\S+)\s+(\S+)\s+(\S+)/;
+		my $key=$';       # everything after last match...
+		$key =~ s/\s*//g;
+		$self->{"flags"}=$flags;
+		$self->{"algorithm"}=$algorithm;
+		$self->{"protocol"}=$protocol;
+		my $keymaterial=decode_base64($key);
+		$self->{"keybin"}=($keymaterial);
+		$self->{"key"}=$key;
+		
+		setkeytag($self);
+	    }
+	return bless $self, $class;
+}
+
+
+
+sub rdatastr {
+	my $self = shift;
+	my $rdatastr;
+	if (exists $self->{"flags"}) {
+	    $rdatastr  = $self->{flags};
+	    $rdatastr .= "  "  . "$self->{protocol}";
+	    $rdatastr .= "  "  . "$self->{algorithm}";
+	    $rdatastr .= " ( \n" ;
+	    # do some nice formatting
+	    my $keystring=$self->{key};
+	    $keystring =~ s/\n//g;
+	    $keystring =~ s/(\S{36})/$1\n\t\t\t/g;
+	    $rdatastr .=  "\t\t\t".$keystring;
+	    $rdatastr .= " \n\t\t\t) ; Key ID = "  . "$self->{keytag}";
+	    }
+	else {
+	    $rdatastr = "; no data";
+	}
+
+	return $rdatastr;
+}
+
+sub rr_rdata {
+    my $self = shift;
+    
+    my $rdata;
+    if (exists $self->{"flags"}) {
+	$rdata= pack("n",$self->{"flags"}) ;
+	$rdata.=
+	    pack("C2",$self->{"protocol"} 
+		     , $self->{"algorithm"}) ;
+	$rdata.= $self->{"keybin"}
+    }
+    return $rdata;
+}
+
+sub setkeytag
+{
+    my $self=shift;
+    if ($self->{"algorithm"} == '1'){
+	# RFC 2535 4.1.6  most significant 16 bits of the least
+	#                 significant 24 bits
+	
+	my @keystr=split //, $self->{"keybin"};
+	my $keysize= $#keystr+1;
+	$self->{"keytag"} = (unpack("C",$keystr[$keysize - 3]) << 8) 
+	    + unpack("C",$keystr[$keysize - 2]);
+	0;
+    }else{
+	# All others
+	# RFC 2535  Appendix C
+	my ($ac, $i);
+	
+
+	# $self->{"rr_data"} cannot be 
+	# used if the object has not been constructed ?!?
+
+	my $rdata= pack("n",$self->{"flags"}) ;   
+	$rdata.=
+	    pack("C2",$self->{"protocol"} 
+		 , $self->{"algorithm"}) ;
+	$rdata.= $self->{"keybin"};
+	my @keyrr=split //, $rdata;
+
+	for ( $ac=0 , $i=0; $i <= $#keyrr ; $i++ ){
+	    $ac += ($i & 1) ? 
+		unpack("C",$keyrr[$i]) :
+		    unpack("C", $keyrr[$i])<<8;
+	}
+	$ac += ($ac>>16) & 0xFFFF;
+	$self->{"keytag"} =($ac & 0xFFFF);
+	0;
+    }
+    
+}
+
+
+
+
+
+1;
+
+
+=head1 NAME
+
+Net::DNS::RR::NXT - DNS NXT resource record
+
+=head1 SYNOPSIS
+
+C<use Net::DNS::RR>;
+
+=head1 DESCRIPTION
+
+Class for DNS Address (KEY) resource records.
+
+=head1 METHODS
+
+=head2 flags
+
+    print "flags" = ", $rr->flags, "\n";
+
+Returns the RR's flags in decimal representation
+
+
+=head2 protocol
+
+    print "protocol" = ", $rr->protocol, "\n";
+
+Returns the RR's protocol field in decimal representation
+
+=head2 algorithm
+
+    print "algoritm" = ", $rr->algorithm, "\n";
+
+Returns the RR's algorithm field in decimal representation
+
+    1 = MD5 RSA
+    2 = DH
+    3 = DSA
+    4 = Elliptic curve
+
+=head2 key
+
+    print "key" = ", $rr->key, "\n";
+
+Returns the key in base64 representation
+
+
+=head2 keybin
+
+    $keybin =  $rr->keybin;
+
+Returns the key binary material
+
+
+=head2 keytag
+
+    print "keytag" = ", $rr->keytag, "\n";
+
+Returns the key tag of the key. (RFC2535 4.1.6)
+
+Read "KeyID Bug in bind." below.
+
+
+
+=head1 KeyID Bug in bind.
+
+Bind used to have a bug in the computation of the keyid ($rr->keytag)
+for keys other then algorithhm RSA. This means that if a signature is
+made with a key with $keyrr->keytag as key id then the $sig->keytag
+will report another value. So be careful with comparing $rr->keytags
+
+This bug was fixed in bind 9.1.2 and bind 8.2.4.
+
+
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 Olaf M. Kolkman. RIPE NCC.  
+
+Based on and contains code by Copyright (c) 1997 Michael Fuhr.
+
+All rights reserved.  This program is free software; you can
+redistribute it and/or modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>,
+L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>,
+RFC 2435 Section 3
+
+=cut
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/LOC.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/LOC.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/LOC.pm	Sun Nov 19 07:05:06 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/LOC.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::LOC;
 
-# $Id: LOC.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: LOC.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA @EXPORT @EXPORT_OK @poweroften $reference_alt
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/MB.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/MB.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/MB.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/MB.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::MB;
 
-# $Id: MB.pm,v 1.4 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: MB.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -50,6 +51,14 @@
 	return $rdata;
 }
 
+sub _canonicalRdata {
+    my $self=shift;
+    my $rdata = "";
+    if (exists $self->{"madname"}) {
+		$rdata .= $self->_name2wire($self->{"madname"});
+	}
+	return $rdata;
+}
 1;
 __END__
 
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/MG.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/MG.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/MG.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/MG.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::MG;
 
-# $Id: MG.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: MG.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -48,6 +49,17 @@
 
 	return $rdata;
 }
+
+
+sub _canonicalRdata {
+    my $self=shift;
+    my $rdata = "";
+    if (exists $self->{"mgmname"}) {
+		$rdata .= $self->_name2wire($self->{"mgmname"});
+	}
+	return $rdata;
+}
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/MINFO.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/MINFO.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/MINFO.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/MINFO.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::MINFO;
 
-# $Id: MINFO.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: MINFO.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -57,6 +58,20 @@
 
 	return $rdata;
 }
+
+
+sub _canonicalRdata {
+	my ($self, $packet, $offset) = @_;
+	my $rdata = "";
+
+	if (exists $self->{"rmailbx"}) {
+		$rdata .= $self->_name2wire($self->{"rmailbx"});
+		$rdata .=  $self->_name2wire($self->{"emailbx"});
+	}
+
+	return $rdata;
+}
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/MR.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/MR.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/MR.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/MR.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::MR;
 
-# $Id: MR.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: MR.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -49,6 +50,17 @@
 
 	return $rdata;
 }
+
+sub _canonicalRdata {
+    my $self=shift;
+    my $rdata = "";
+    if (exists $self->{"newname"}) {
+		$rdata .= $self->_name2wire($self->{"newname"});
+	}
+	return $rdata;
+}
+
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/MX.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/MX.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/MX.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/MX.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::MX;
 
-# $Id: MX.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: MX.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -57,6 +58,19 @@
 
 	return $rdata;
 }
+
+sub _canonicalRdata {
+    my ($self) = @_;
+    my $rdata = "";
+    
+    if (exists $self->{"preference"}) {
+	$rdata .= pack("n", $self->{"preference"});
+	$rdata .= $self->_name2wire($self->{"exchange"})
+	}
+    
+    return $rdata;
+}
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NAPTR.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NAPTR.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NAPTR.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NAPTR.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::NAPTR;
 
-# $Id: NAPTR.pm,v 1.6 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: NAPTR.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NIMLOC.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NIMLOC.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NIMLOC.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NIMLOC.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::NIMLOC;
 
-# $Id: NIMLOC.pm,v 1.2 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: NIMLOC.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NS.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NS.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NS.pm	Sun Nov 19 07:05:07 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NS.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::NS;
 
-# $Id: NS.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: NS.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -49,6 +50,17 @@
 
 	return $rdata;
 }
+
+
+
+sub _canonicalRdata {
+    # rdata contains a compressed domainname... we should not have that.
+	my ($self) = @_;
+	my $rdata;
+	$rdata=$self->_name2wire($self->{"nsdname"});
+	return $rdata;
+}
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NSAP.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NSAP.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NSAP.pm	Sun Nov 19 07:05:08 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NSAP.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::NSAP;
 
-# $Id: NSAP.pm,v 1.3 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: NSAP.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NULL.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NULL.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NULL.pm	Sun Nov 19 07:05:08 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NULL.pm	Mon Apr 23 13:05:01 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::NULL;
 
-# $Id: NULL.pm,v 1.2 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: NULL.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/NXT.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/NXT.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/NXT.pm	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/NXT.pm	Mon Apr 23 13:05:01 2001
@@ -0,0 +1,200 @@
+package Net::DNS::RR::NXT;
+
+# $Id: NXT.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
+
+use strict;
+use vars qw(@ISA);
+use Carp;
+
+use Socket;
+use Net::DNS;
+use Net::DNS::Packet;
+
+
+use Carp;
+
+@ISA = qw(Net::DNS::RR);
+
+sub new {
+    my ($class, $self, $data, $offset) = @_;
+    
+    if ($self->{"rdlength"} > 0) {
+	my($nxtdname,$nxtoffset) = 
+	  Net::DNS::Packet::dn_expand($data, $offset);
+
+	$self->{"nxtdname"} = "$nxtdname";
+
+	my $typebm =substr($$data,$nxtoffset,
+				 $self->{"rdlength"}-
+				 $nxtoffset+$offset);
+
+	$self->{"typebm"}=$typebm;
+	$self->{"typelist"} = join " " 
+	    ,  _typebm2typestr($typebm);
+    }
+    
+    return bless $self, $class;
+}
+
+sub new_from_string {
+    my ($class, $self, $string) = @_;
+    if ($string) {
+	$string =~ tr/()//d;
+	$string =~ s/;.*$//mg;
+	my ($nxtdname) = 
+	    $string =~ /^\s*(\S+)\s+/;
+	my @nxttypes = split /\s+/ , $';       # everything after last match...
+	
+	$self->{"nxtdname"}= lc($nxtdname) ;
+	$self->{"typelist"}= join " " ,@nxttypes ;
+	$self->{"typebm"}=_typestr2typebm(@nxttypes);
+	
+    }
+    return bless $self, $class;
+}
+
+
+sub rdatastr {
+	my $self = shift;
+	my $rdatastr;
+
+	if (exists $self->{"nxtdname"}) {
+	    $rdatastr  = $self->{nxtdname};
+	    $rdatastr .= "  "  . "$self->{typelist}";
+	    }
+	else {
+	    $rdatastr = "; no data";
+	}
+
+	return $rdatastr;
+}
+
+sub rr_rdata {
+    my ($self, $packet, $offset) = @_;
+    my $rdata = "" ;
+    if (exists $self->{"nxtdname"}) {
+	# Compression used here... 
+	$rdata = $packet->dn_comp($self->{"nxtdname"},$offset);
+	$rdata .= $self->{"typebm"};
+    }
+    
+    return $rdata;
+    
+}
+
+
+
+sub _canonicalRdata {
+    # rdata contains a compressed domainname... we should not have that.
+	my ($self) = @_;
+	my $rdata;
+
+	$rdata=$self->_name2wire($self->{"nxtdname"});
+	$rdata .= $self->{"typebm"};	
+	return $rdata;
+}
+
+
+sub _typestr2typebm {
+    # RFC2535 5.1 needs the typebm
+    # This needs to check for values > 127....
+
+    # Sets a bit for every qtype in the input array.
+    # Minimum bitmaplenght 4 octets because NXT (30) is allways there
+    # may be longer but trailing all zero octets should be dropped.
+
+    my (@typelist, @typebitarray);
+    @typelist= @_;
+    for(my $i=0;$i < @typelist; $i++){
+	$typebitarray[$Net::DNS::typesbyname{uc($typelist[$i])}]=1;
+    }
+    
+    my $finalsize;
+    if ( @typebitarray % 4){
+	use integer;
+	$finalsize = 8 * ((@typebitarray / 8)  + 1);
+    }
+    for (my $i=0;$i< $finalsize; $i++){
+	$typebitarray[$i]=0 if ! defined $typebitarray[$i];
+    }
+    my $typebm= pack("B$finalsize",join "", @typebitarray );
+    return $typebm
+
+}
+
+sub _typebm2typestr {
+    # RFC2535 5.1 needs the typebm
+    # This needs to check for values > 127....
+    my @typebm=split //, unpack("B*", shift);  # bit representation in array
+    my @typelist;
+    carp "Cannot deal with qtype > 127" 
+	if ($#typebm > 127);
+    
+    my($foo);
+    foreach $foo (keys(%Net::DNS::typesbyval)  ){
+	next if $foo > $#typebm;           # Skip larger aray vallues.
+	@typelist=(@typelist,$Net::DNS::typesbyval{$foo}) if 
+	    ($typebm[$foo] eq "1");
+    }
+
+    return @typelist;
+}
+
+
+1;
+
+
+=head1 NAME
+
+Net::DNS::RR::NXT - DNS NXT resource record
+
+=head1 SYNOPSIS
+
+C<use Net::DNS::RR>;
+
+=head1 DESCRIPTION
+
+Class for DNS Address (NXT) resource records.
+
+=head1 METHODS
+
+=head2 nxtdname
+
+    print "nxtdname" = ", $rr->nxtdname, "\n";
+
+Returns the RR's next domain name field.
+
+
+=head2 typelist
+
+    print "typelist" = ", $rr->typelist, "\n";
+
+Returns a string with the list of qtypes for which data exists for
+this particular label.
+
+
+
+=head2 typebm
+
+    print "typebm" = " unpack("B*", $rr->typebm), "\n";
+
+Same as the typelist but now in a representation  bitmap as in 
+specified in the RFC. This is not the kind of method you will need
+on daily basis.
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 Olaf M. Kolkman. RIPE NCC.  
+
+Based on and contains code by Copyright (c) 1997 Michael Fuhr.
+
+All rights reserved.  This program is free software; you can
+redistribute it and/or modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>,
+L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>,
+RFC 2435 Section 5
+
+=cut
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/OPT.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/OPT.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/OPT.pm	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/OPT.pm	Mon Apr 23 13:05:02 2001
@@ -0,0 +1,212 @@
+package Net::DNS::RR::OPT;
+
+# $Id: OPT.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
+
+
+use strict;
+use vars qw(@ISA %extendedrcodesbyname %extendedrcodesbyval $EDNSVERSION);
+
+use Socket;
+use Net::DNS;
+use Carp;
+
+@ISA = qw(Net::DNS::RR);
+
+$EDNSVERSION= 0 ;
+
+%extendedrcodesbyname = (
+	"ONLY_RDATA"	=> 0,		# No name specified see 4.6 of 2671 
+        "UNDEF1"	=> 1,
+        "UNDEF2"	=> 2,
+        "UNDEF3"	=> 3,
+        "UNDEF4"	=> 4,
+        "UNDEF5"	=> 5,
+        "UNDEF6"	=> 6,
+        "UNDEF7"	=> 7,
+        "UNDEF8"	=> 8,
+        "UNDEF9"	=> 9,
+        "UNDEF10"	=> 10,
+        "UNDEF11"	=> 11,
+        "UNDEF12"	=> 12,
+        "UNDEF13"	=> 13,
+        "UNDEF14"	=> 14,
+        "UNDEF15"	=> 15,
+	"BADVERS"	=> 16,		# RFC 2671
+);
+%extendedrcodesbyval = map { ($extendedrcodesbyname{$_} => $_) } keys %extendedrcodesbyname;
+
+
+
+sub new {
+    my ($class, $self, $data, $offset) = @_;
+    if ($self->{"rdlength"} > 0) {
+	$self->{"optioncode"}=unpack("n",substr($$data,$offset,2));
+	$self->{"optionlength"}=unpack("n",substr($$data,$offset+2,2));
+	$self->{"optiondata"}=unpack("n",substr($$data,$offset+4,$self->{"optionlength"}));
+    }else{	
+	$self->{"optioncode"}=0;
+	$self->{"optionlength"}=0;
+	$self->{"optiondata"}=0;
+    }
+    $self->{"_rcode_flags"}=pack("N",$self->{"ttl"});
+    $self->{"extendedrcode"}=unpack("C",substr($self->{"_rcode_flags"},0,1));
+    $self->{"ednsversion"}=unpack("C",substr($self->{"_rcode_flags"},1,1));
+    $self->{"ednsflags"}=unpack("n",substr($self->{"_rcode_flags"},2,2));
+    
+    
+    return bless $self, $class;
+}
+
+
+
+
+
+sub new_from_string {
+    my ($class, $self ) = @_;
+    # There is no such thing as an OPT RR in a ZONE file. 
+    # Not implemented!
+    croak "You should not try to create a OPT RR from a string\nNot implemented";
+    return bless $self, $class;
+}
+
+
+
+
+sub new_from_hash {
+    my ($class, $self ) = @_;
+
+    $self->{"name"} = "" ;   # should allway be "root"
+    # Setting the MTU smaller then 512 does not make sense 
+    # should we test for a maximum here?
+    if ( $self->{"class"} eq "IN" ||  $self->{"class"} <512 ){
+	$self->{"class"} = 512;    # Default value...
+    }
+    
+    $self->{"extendedrcode"}   = 0 unless exists $self->{"extendedrcode"};
+    $self->{"ednsflags"}  = 0 unless exists $self->{"ednsflags"};
+    $self->{"ttl"}= unpack ("N", 
+			  pack("C", $self->{"extendedrcode"} ) .
+			  pack("C", $Net::DNS::RR::OPT::EDNSVERSION )  .
+			  pack("n", $self->{"ednsflags"}));
+
+    if (exists  $self->{"optioncode"}) {
+	$self->{"optiondata"} = "" if ! exists  $self->{"optiondata"};
+	$self->{"optionlength"}= length $self->{"optiondata"}
+    }
+    return bless $self, $class;
+
+}
+
+
+
+
+sub string {
+   my  $self=shift;
+    return "; EDNS Version ". $self->{"ednsversion"} . 
+        "\t UDP Packetsize: " .  $self->{"class"} . 
+	"\n; EDNS-RCODE:\t". $self->{"extendedrcode"} .
+	   " (" . $extendedrcodesbyval{ $self->{"extendedrcode"} }. ")" .
+	"\n; EDNS-FLAGS:\t". sprintf "0x%04x", $self->{"ednsflags"} .
+	"\n";
+
+    }
+
+
+sub rdatastr {
+	my $self = shift;
+	my $rdatastr;
+	$rdatastr = "; Parsing of OPT rdata is not yet implemented";
+	return $rdatastr;
+}
+
+
+
+
+
+sub rr_rdata {
+    my $self = shift;
+    my $rdata;
+    if (exists $self->{"optioncode"}) {
+	$rdata= pack("n",$self->{"optioncode"}) ;
+	$rdata.= pack("n",$self->{"optionlength"}); 
+	$rdata.= $self->{"optiondata"}
+    } else {
+	$rdata="";
+    }
+    return $rdata;
+}
+
+
+
+
+
+1;
+
+
+=head1 NAME
+
+Net::DNS::RR::OPT - DNS OPT
+
+=head1 SYNOPSIS
+
+C<use Net::DNS::RR>;
+
+=head1 DESCRIPTION
+
+Class for EDNS pseudo resource record OPT.
+
+=head1 METHODS
+
+This object should only be used inside the Net::DNS classes itself.
+
+=head2 new 
+
+Since "OPT" is a pseudo record and should not be stored in masterfiles we
+have not implemented a method to create this RR from string.
+
+One may create the object from a hash. See RFC 2671 for details
+
+$rr= new Net::DNS::RR {
+    name => "",     # Ignored and set to ""
+    type => "OPT",  
+    class => 1024,    # sets UDP payload size
+    extendedrcode =>  0x00,    # sets the extended RCODE 1 octets
+    ednsflags     =>  0x0000,  # sets the ednsflags (2octets)  
+    optioncode   =>   0x0      # 2 octets
+    optiondata   =>   0x0      # optionlength octets
+}    
+
+The ednsversion is set to 0 for now. The ttl value is determined from 
+the extendedrcode, the ednsversion and the ednsflag.
+The rdata is constructed from the optioncode and optiondata 
+see section 4.4 of RFC 2671
+
+If optioncode is left undefined then we do not expect any RDATA.
+
+The defaults are no rdata.   
+
+
+=head1 TODO
+
+- This class is tailored to use with dnssec. 
+- Do some range checking on the input.
+- This class probably needs subclasses once OPTION codes start to be defined.
+- look at use of extended labels
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 Olaf M. Kolkman. RIPE NCC.  
+
+Based on and contains code by Copyright (c) 1997 Michael Fuhr.
+
+All rights reserved.  This program is free software; you can
+redistribute it and/or modify it under the same terms as Perl itself.
+
+
+=head1 SEE ALSO
+
+L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>,
+L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>,
+RFC 2435 Section 3
+
+=cut
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/PTR.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/PTR.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/PTR.pm	Sun Nov 19 07:05:08 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/PTR.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::PTR;
 
-# $Id: PTR.pm,v 1.5 2000/11/19 06:04:45 mfuhr Exp mfuhr $
+# $Id: PTR.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -45,6 +46,17 @@
 
 	if (exists $self->{"ptrdname"}) {
 		$rdata .= $packet->dn_comp($self->{"ptrdname"}, $offset);
+	}
+
+	return $rdata;
+}
+
+sub  _canonicalRdata {
+	my ($self, $packet, $offset) = @_;
+	my $rdata = "";
+
+	if (exists $self->{"ptrdname"}) {
+		$rdata .= $self->_name2wire($self->{"ptrdname"});
 	}
 
 	return $rdata;
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/PX.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/PX.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/PX.pm	Sun Nov 19 07:05:36 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/PX.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::PX;
 
-# $Id: PX.pm,v 1.4 2000/11/19 06:05:23 mfuhr Exp mfuhr $
+# $Id: PX.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -64,6 +65,27 @@
 
 		$rdata .= $packet->dn_comp($self->{"mapx400"},
 					    $offset + length $rdata);
+	}
+
+	return $rdata;
+}
+
+
+
+
+
+sub _canonicalRdata {
+	my ($self) = shift;
+	my $rdata = "";
+
+	if (exists $self->{"preference"}) {
+		$rdata .= pack("n", $self->{"preference"});
+
+		$rdata .= $self->_name2wire($self->{"map822"});
+					   
+
+		$rdata .= $self->_name2wire($self->{"mapx400"});
+
 	}
 
 	return $rdata;
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/RP.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/RP.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/RP.pm	Sun Nov 19 07:06:06 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/RP.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::RP;
 
-# $Id: RP.pm,v 1.5 2000/11/19 06:05:52 mfuhr Exp mfuhr $
+# $Id: RP.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -56,6 +57,21 @@
 
 	return $rdata;
 }
+
+
+sub _canonicalRdata {
+    my $self = shift;
+    my $rdata = "";
+    
+    if (exists $self->{"mbox"}) {
+	$rdata .= $self->_name2wire($self->{"mbox"});
+	$rdata .=  $self->_name2wire($self->{"txtdname"});
+	
+    }
+    return $rdata;
+}
+
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/RT.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/RT.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/RT.pm	Sun Nov 19 07:06:06 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/RT.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::RT;
 
-# $Id: RT.pm,v 1.5 2000/11/19 06:05:52 mfuhr Exp mfuhr $
+# $Id: RT.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -53,6 +54,17 @@
 		$rdata .= $packet->dn_comp($self->{"intermediate"},
 					   $offset + length $rdata);
 	}
+
+	return $rdata;
+}
+sub _canonicalRdata {
+	my ($self, $packet, $offset) = @_;
+	my $rdata = "";
+
+	if (exists $self->{"preference"}) {
+		$rdata .= pack("n", $self->{"preference"});
+		$rdata .= $self->_name2wire($self->{"intermediate"});
+	    }
 
 	return $rdata;
 }
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/SIG.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/SIG.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/SIG.pm	Thu Jan  1 01:00:00 1970
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/SIG.pm	Mon Apr 23 13:05:02 2001
@@ -0,0 +1,624 @@
+package Net::DNS::RR::SIG;
+
+#RFC 2535 section 4
+
+# $Id: SIG.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
+
+
+my $debug=0;
+
+
+use strict;
+use vars qw(@ISA);
+
+use Socket;
+use Net::DNS;
+use Carp;
+
+@ISA = qw(Net::DNS::RR);
+
+sub new {
+    my ($class, $self, $data, $offset) = @_;
+    if ($self->{"rdlength"} > 0) {
+	#RFC2535 section 4.1
+	my $offsettoalg=$offset+2;
+	my $offsettolabels=$offset+3;
+	my $offsettoorgttl=$offset+4;
+	my $offsettosigexp=$offset+8;
+	my $offsettosiginc=$offset+12;
+	my $offsettokeytag=$offset+16;
+	my $offsettosignm=$offset+18;
+
+
+	$self->{"typecovered"}= _type2string(unpack("n",substr($$data,$offset,2)));
+	$self->{"algorithm"}=unpack("C",substr($$data,$offsettoalg,1));
+	$self->{"labels"}=lc(unpack("C",substr($$data,$offsettolabels,1)));
+	$self->{"orgttl"}=unpack("N",substr($$data,$offsettoorgttl,4));
+	my @expt=gmtime(unpack("N",substr($$data,$offsettosigexp,4)));
+	$self->{"sigexpiration"}= sprintf ("%d%02d%02d%02d%02d%02d",
+					   $expt[5]+1900 ,$expt[4]+1 , 
+					   $expt[3] ,$expt[2] , $expt[1]  , 
+					   $expt[0]);
+	my @inct=gmtime(unpack("N",substr($$data,$offsettosiginc,4)));
+	$self->{"siginceptation"}=  sprintf ("%d%02d%02d%02d%02d%02d",
+					     $inct[5]+1900 ,$inct[4]+1 , 
+					     $inct[3] ,$inct[2] , $inct[1]  ,
+					     $inct[0]);
+	$self->{"keytag"}=unpack("n",substr($$data,$offsettokeytag,2));
+
+
+
+	my($signame,$sigoffset) = Net::DNS::Packet::dn_expand
+	    ($data, $offsettosignm);
+	$self->{"signame"}=lc($signame);
+	my($sigmaterial)=substr($$data,$sigoffset,
+				($self->{"rdlength"}-$sigoffset+$offset));
+	$self->{"sigbin"}=$sigmaterial;
+	use MIME::Base64;
+	
+	$self->{"sig"}= encode_base64($sigmaterial);
+
+	$self->{"vrfyerrstr"}="";
+	
+    }
+    return bless $self, $class;
+}
+
+
+
+
+sub new_from_string {
+    my ($class, $self, $string) = @_;
+    
+    
+    
+    if ($string) {
+	$string =~ tr/()//d;
+	$string =~ s/;.*$//mg;
+	my ($typecovered, $algoritm,
+	    $labels, $orgttl, $sigexpiration,
+	    $siginceptation, $keytag,$signame) = 
+		$string =~ 
+		    /^\s*(\S+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\S+)/;
+	croak (" Invallid SIG RR, check your fomat ") if !$keytag;
+	my $sig=$';       # everything after last match...
+	$sig =~ s/\s*//g;
+	$self->{"typecovered"}= $typecovered;
+	$self->{"algorithm"}= $algoritm;
+	$self->{"labels"}= lc($labels);
+	$self->{"orgttl"}= $orgttl;
+	$self->{"sigexpiration"}=  $sigexpiration;
+	$self->{"siginceptation"}= $siginceptation;
+	$self->{"keytag"}= $keytag;
+	$self->{"signame"}= lc($signame);
+	$self->{"sig"}= $sig;
+	use MIME::Base64;
+	my $sigmaterial=decode_base64($sig);
+	$self->{"sigbin"}= $sigmaterial;
+	$self->{"vrfyerrstr"}="";
+    }
+    return bless $self, $class;
+}
+
+
+sub rdatastr {
+	my $self = shift;
+	my $rdatastr;
+
+
+
+	if (exists $self->{"typecovered"}) {
+	    $rdatastr  = $self->{typecovered};
+	    $rdatastr .= "  "  . "$self->{algorithm}";
+	    $rdatastr .= "  "  . "$self->{labels}";
+	    $rdatastr .= "  "  . "$self->{orgttl}";
+	    $rdatastr .= "  "  . "$self->{sigexpiration}";
+	    $rdatastr .= " (\n\t\t\t"  . "$self->{siginceptation}";
+	    $rdatastr .= " "  . "$self->{keytag}";
+	    $rdatastr .= "  "  . "$self->{signame}";
+	    # do some nice formatting
+	    my $sigstring=$self->{sig};
+	    $sigstring =~ s/\n//;
+	    $sigstring =~ s/(\S{36})/$1\n\t\t\t/g;
+	    $rdatastr .=  "\n\t\t\t".$sigstring;
+	    $rdatastr .= " ) ";
+	    }
+	else {
+	    $rdatastr = "; no data";
+	}
+
+	return $rdatastr;
+}
+
+sub rr_rdata {
+    my ($self, $packet, $offset) = @_;
+    my $rdata = "";
+    if (exists $self->{"typecovered"}) {
+	$rdata  = pack("n",_string2type($self->{typecovered}));
+	$rdata .= pack("C",$self->{algorithm});
+	$rdata .= pack("C",$self->{"labels"});
+	$rdata .= pack("N",$self->{"orgttl"});
+	use Time::Local;
+	$self->{"sigexpiration"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
+	$rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900));
+
+	$self->{"siginceptation"} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
+	$rdata .= pack("N",timegm ($6, $5, $4, $3, $2-1, $1-1900));
+	$rdata .= pack("n",$self->{"keytag"});
+	
+	
+	# Since we will need canonical and expanded names while checking 
+	# we do not use the packet->dn_comp here but use RFC1035 p10.
+	{   my @dname= split /\./,lc($self->{"signame"});
+	    for (my $i=0;$i<@dname;$i++){
+		$rdata .= pack ("C",length $dname[$i] );
+		$rdata .= $dname[$i] ;
+
+	    }
+	    $rdata .= pack ("C","0");
+	}
+
+	$rdata .= $self->{"sigbin"};
+    }
+    
+    return $rdata;
+    
+}
+
+
+
+sub verify {
+    my ($self, $datarrset, $keyrr) = @_;
+    # Reminder...
+    # $datarrset is a reference to an array of RR objects:
+    # $datarrset->[$i]->method  is the call to the method of the 
+    # $i th object in the array...
+    # @{$datarrset} is length of the array when called in numerical context
+    $self->{"vrfyerrstr"}="---- Unknown Error Condition ------";
+    print "\n ------------------------------- SIG DEBUG  -----------------\n"  if $debug;
+    print "\n  SIG:\t", $self->string if $debug;
+    for (my $i=0; $i<@{$datarrset}; $i++){
+	print "\n DATA:\t", $datarrset->[$i]->string if $debug ;
+    }
+    print "\n  KEY:\t" , $keyrr->string if $debug;
+    print "\n ------------------------------------------------------------\n" if $debug;
+    my $message ;  # this is the data from that is signed, it will be
+    		   # fed to the verifier. See RFC2535 4.1.8 on how this 
+                   # string is constructed
+
+
+    if ($datarrset->[0]->type ne $self->typecovered ) {
+	$self->{"vrfyerrstr"} = "\nCannot verify datatype  " . $self->typecovered . 
+	    " with a key intended for " . 
+		$datarrset->[0]->type .
+		    " verification\n";
+	return 0;
+    }
+
+    if ( !$datarrset->[0]->type eq "SIG" ) {
+	# if [0] has type SIG the whole RRset is type SIG. 
+	# There are no SIGs over SIG RRsets
+	$self->{"vrfyerrstr"} = 
+	    "SIGs over SIGs???\n" .
+ 	   " What are you trying to do. This is not possible.\n";
+	return 0;
+    }
+
+
+    # construction of message
+    my $rdatawithoutsig=substr($self->rr_rdata , 0, 
+				  ((length  $self->rr_rdata) - 
+				   (length  $self->sigbin) ));
+    print "\n\nstrip:\t",  unpack("H*", $rdatawithoutsig) if $debug;
+    
+
+    $message= $rdatawithoutsig;
+
+    # Ordered RR set RFC2535 section 8.3
+
+    my @canonicaldataarray;
+
+    for (my $i=0; $i<@{$datarrset}; $i++){
+	print "\n\nCan Data RR: $i\t", 
+	unpack("H*", ($datarrset->[$i]->_canonicaldata)) if $debug;
+	$canonicaldataarray[$i]=$datarrset->[$i]->_canonicaldata;
+    }
+
+
+    #  Fortunately the PERL sort routine has the behaviour as specified in
+    #  2535 section 8.3
+    my @sortedcanonicaldataarray= sort @canonicaldataarray;
+    
+    for (my $i=0; $i<@sortedcanonicaldataarray ; $i++){
+	$message .=  $sortedcanonicaldataarray[$i];
+    }
+    print "\n message:\t",  unpack("H*",$message) if $debug;
+    
+    
+    my $signature=$self->sigbin; 
+    print "\n signature:\t", unpack("H*",$signature) if $debug;
+    my $verified=0;
+    if ( $self->algorithm == 1 ){    #Verifying for RSA
+	$verified=$self->_verifyRSA($message,$signature,$keyrr) || return 0;
+    }     
+    elsif ( $self->algorithm == 3 )  # Verifying for DSA
+    {
+	 $verified=$self->_verifyDSA($message,$signature,$keyrr) || return 0;
+    }
+    else                                  # Verifying other algorithms
+    { 
+	$self->{"vrfyerrstr"}= "Algoritm ". $self->algorithm . " has not yet been implemented";
+	return 0;
+    }	
+    
+    # This really is a redundant test
+    if ($verified) {  
+        # time to do some time checking.
+	# This is ugly but we have the siginceptation and expiration as strings
+	# so instead of converting those to long we'll compare strings..
+	my @inct=gmtime(time);
+	my $currentdatestring=  sprintf ("%d%02d%02d%02d%02d%02d",
+					     $inct[5]+1900 ,$inct[4]+1 , 
+					     $inct[3] ,$inct[2] , $inct[1]  ,
+					     $inct[0]);	
+
+	if ($self->{"siginceptation"} > $currentdatestring ){
+	    $self->{"vrfyerrstr"}= "Signature may only be used in the future; after " .
+		$self->{"siginceptation"} ;
+	    return 0;
+	}elsif($self->{"sigexpiration"} < $currentdatestring ){
+	    $self->{"vrfyerrstr"}= "Signature has expired since: " .
+		$self->{"sigexpiration"} ;
+	    return 0;
+	}
+	$self->{"vrfyerrstr"}= "No Error";
+	return 1;
+    }
+    
+    $self->{"vrfyerrstr"}="Verification method error.";
+    return 0;
+
+} #END verify block
+
+
+
+
+
+#
+# To do:  make these functions invisable outside the class.
+#
+sub _type2string {
+    my $index=shift;
+    if( exists $Net::DNS::typesbyval{$index}){
+	return $Net::DNS::typesbyval{$index} ;
+    }else{
+	return "UNKNOWN TYPE";
+    }
+}
+
+sub _string2type {
+    my $index=shift;
+        if( exists $Net::DNS::typesbyname{uc($index)}){
+	return $Net::DNS::typesbyname{uc($index)} ;
+    }else{
+	carp "UNKNOWN QTYPE, cannot continue ";
+    }
+}
+
+
+
+
+
+
+sub _verifyDSA {
+    my ($self, $message, $signature, $keyrr) = @_; 
+    # RSA RFC2536
+    #
+    # Setup a DSA::Key. 
+    #
+    use Crypt::DSA;
+
+    # first extract variables from the keymaterial (RFC2535 section2)
+    # Also read FIPS PUB 186 (Federal Information Processing Standards Publication 186
+    # 
+    # Public Key Elements
+    my $T_field_key=&Crypt::DSA::Util::bin2mp(substr($keyrr->keybin,
+						 0,
+						 1));
+    my $Q_field=&Crypt::DSA::Util::bin2mp(substr($keyrr->keybin, 
+						 1,
+						 20));
+    my $P_field=&Crypt::DSA::Util::bin2mp(substr($keyrr->keybin, 
+						 21, 
+						 64+$T_field_key*8)) ;
+    my $G_field=&Crypt::DSA::Util::bin2mp(substr($keyrr->keybin, 
+						 21+64+$T_field_key*8,
+						 64+$T_field_key*8));
+    my $Y_field=&Crypt::DSA::Util::bin2mp(substr($keyrr->keybin, 
+						 21+2*(64+$T_field_key*8),
+						 64+$T_field_key*8)) ;
+    
+    if ( $debug ) {
+	print "\n\n------------Studying DSA key content.-----------------".
+	    "\n KEY MAT=". unpack("H*",$keyrr->keybin);
+	print "\n T_field=". unpack("H*",substr($keyrr->keybin,
+						0,
+						1));
+	print "\n T_field=". $T_field_key;
+	print "\n Q_field=". unpack("H*",substr($keyrr->keybin, 
+						1,
+						20));
+	print "\n Q_field=". $Q_field;
+	print "\n P_field=". unpack("H*",,substr($keyrr->keybin, 
+						 21, 
+						 64+$T_field_key*8)) ;
+	print "\n P_field=". $P_field;
+	print "\n G_field=". unpack("H*",substr($keyrr->keybin, 
+						21+64+$T_field_key*8,
+						64+$T_field_key*8));
+	print "\n G_field=". $G_field;
+	print "\n Y_field=". unpack("H*",substr($keyrr->keybin, 
+						21+2*(64+$T_field_key*8),
+						64+$T_field_key*8)) ;
+	print "\n Y_field=". $Y_field;
+	print "\n-----------------------------\n";
+    }
+    
+    my $dsa= new Crypt::DSA;
+    my $dsakey= new Crypt::DSA::Key;
+    
+    $dsakey->p($P_field);       # See FIPS186 section 4
+    $dsakey->g($G_field);
+    $dsakey->q($Q_field);
+    $dsakey->pub_key($Y_field); 
+
+    # Signature elements.  (See RFC2536 section 3 and FIPS186 section 5)
+
+    my $T_field_sig=&Crypt::DSA::Util::bin2mp(substr($self->sigbin,
+						 0,
+						 1));
+    my $R_field=&Crypt::DSA::Util::bin2mp(substr($self->sigbin,
+						 1,
+						 20));
+    my $S_field=&Crypt::DSA::Util::bin2mp(substr($self->sigbin,
+						 21,
+						 20));
+
+    if ( $debug ) {
+	print "\n\n------------Studying DSA sig content.-----------------".
+	    "\n SIG MAT=". unpack("H*",$self->sigbin);
+	print "\n T_field=". unpack("H*",substr($self->sigbin,
+						0,
+						1));
+	print "\n T_field=". $T_field_sig;
+	print "\n R_field=". unpack("H*",substr($self->sigbin, 
+						1,
+						20));
+	print "\n R_field=". $R_field;
+	print "\n S_field=". unpack("H*",,substr($self->sigbin, 
+						 21, 
+						 20)) ;
+	print "\n S_field=". $S_field;
+	print "\n-----------------------------\n";
+    }
+    
+    my $dsasig= new Crypt::DSA::Signature;
+    $dsasig->r($R_field);
+    $dsasig->s($S_field);
+
+    if ( $dsa->verify ( 
+			Message => $message,
+			Signature => $dsasig,
+			Key => $dsakey,
+			)){
+	$self->{"vrfyerrstr"}="DSA Verification successful ";
+	return(1);
+    }else{
+	$self->{"vrfyerrstr"}="DSA Verification failed ";
+    }
+    
+    $self->{"vrfyerrstr"}="DSA Verification failed: undefined error ";
+    
+    return 0;
+}
+sub _verifyRSA {
+    my ($self, $message, $signature, $keyrr) = @_; 
+    # RSA RFC2535
+    #
+    # Setup a RSA::Key::Public object. The documentation is not so clear
+    # on how to fill this object. Turns out you have to look in what the
+    # AUTOLOAD of Crypt::RSA::Key::Public does.
+    #
+    use Crypt::RSA::SS::PKCS1v15 ;
+    use Crypt::RSA::Key::Public;
+    my $pkcs = new Crypt::RSA::SS::PKCS1v15 (
+					     Digest => 'MD5'
+					     );
+    # first extract variables from the keymaterial
+    my $explength;
+    my $exponent;
+    my $modulus;
+    {   #localise dummy
+	my $dummy=1;
+	# determine exponent length
+	
+	#RFC 2537 sect 2
+	($dummy, $explength)=unpack("Cn",$keyrr->keybin) 
+	    if ! ($explength=unpack("C",$keyrr->keybin));
+	print "\n\nEXPLENGTH:",$explength if $debug;
+	
+	# We are constructing the exponent and modulus as a hex number so 
+	# the AUTOLOAD function in Crypt::RSA::Key::Public can deal with it
+	# later, there must be better ways to do this,
+	if ($dummy) { # skip one octet
+	    $exponent=&Crypt::DSA::Util::bin2mp(substr ($keyrr->keybin, 
+							1, 
+							$explength));
+
+	    $modulus=&Crypt::DSA::Util::bin2mp( substr ($keyrr->keybin, 
+							1+$explength, 
+							(length $keyrr->keybin) - 1
+							- $explength));
+	    
+
+	}else{ # skip two octets
+	    $exponent=&Crypt::DSA::Util::bin2mp(substr ($keyrr->keybin, 
+							3,
+							$explength));
+	    
+	    $modulus=&Crypt::DSA::Util::bin2mp( substr ($keyrr->keybin, 
+							3+$explength, 
+							(length $keyrr->keybin) - 3
+							- $explength));
+	}
+    }
+    use  Crypt::RSA::Key::Public;
+    my $rsapubkey = new Crypt::RSA::Key::Public( );
+    # set the modulus
+    $rsapubkey->n($modulus);
+    $rsapubkey->e($exponent);
+    if ($pkcs->verify (
+		       Message    => $message,
+		       Signature  => $signature,
+		       Key        => $rsapubkey,
+		       ))
+    {
+	print "\n VERIFIED" if $debug ;
+	$self->{"vrfyerrstr"}="RSA Verification successful";
+	return 1;
+    }else
+    {   $self->{"vrfyerrstr"}="RSA Verification failed; " .$pkcs->errstr;
+	# Data is not verified
+	print "\nNOT VERIFIED" if $debug;
+	return 0;
+    }
+
+    $self->{"vrfyerrstr"}="RSA Verification failed: undefined error ";
+    0;
+
+}
+
+
+
+
+
+1;
+
+
+=head1 NAME
+
+Net::DNS::RR::SIG - DNS NXT resource record
+
+=head1 SYNOPSIS
+
+C<use Net::DNS::RR>;
+
+=head1 DESCRIPTION
+
+Class for DNS Address (SIG) resource records.
+
+=head1 METHODS
+
+
+=head2 typecovered
+
+    print "typecovered =", $rr->typecovered, "\n"
+
+Returns the qtype covered by the sig.
+
+=head2 algorithm
+
+    print "algorithm =", $rr->algorithm, "\n"
+
+Returns the algorithm number used for the signature
+
+=head2 labels
+
+    print "labels =", $rr->labels, "\n"
+
+Returns the the number of labels of the RRs over wich the 
+sig was made.
+
+=head2 orgttl
+
+    print "orgttl =", $rr->orgttl, "\n"
+
+Returns the RRs the original TTL of the signature
+
+=head2 sigexpiration
+
+    print "sigexpiration =", $rr->sigexpiration, "\n"
+
+Returns the expiration date of the signature
+
+=head2 siginceptation
+
+    print "siginceptation =", $rr->siginceptation, "\n"
+
+Returns the date the signature was incepted.
+
+=head2 keytag
+
+    print "keytag =", $rr->keytag, "\n"
+
+Returns the the keytag (key id) of the key the sig was made with.
+Read "KeyID Bug in bind." below.
+
+=head2 signame
+
+    print "signame =", $rr->signame, "\n"
+
+Returns the name of the public KEY RRs  this sig was made with.
+
+=head2 sig
+
+    print "sig =", $rr->sig, "\n"
+
+Returns the base64 representation of the signature.
+
+
+=head2 verify and vrfyerrstr
+
+    $sigrr->verify(\@datarrset, $keyrr) || croak $sigrr->vrfyerrstr;
+
+Verifies the the RRset stored in the object array @datarrset against
+the signature contained in the $sigrr object itself using the public
+key in $keyrr.  Because of the KeyID bug in bind (see below) a check on 
+keyid is not performed.
+
+Returns 0 on error and sets $sig->vrfyerrstr
+
+
+
+
+
+=head1 KeyID Bug in bind.
+
+Bind used to have a bug in the computation of the keyid ($rr->keytag)
+for keys other then algorithhm RSA. This means that if a signature is
+made with a key with $keyrr->keytag as key id then the $sig->keytag
+will report another value. So be careful with comparing $rr->keytags
+
+This bug was fixed in bind 9.1.2 and bind 8.2.4.
+
+
+=head1 TODO
+
+Clean up the code...
+
+=head1 COPYRIGHT
+
+Copyright (c) 2001 Olaf M. Kolkman. RIPE NCC.  
+
+Based on and contains code by Copyright (c) 1997 Michael Fuhr.
+
+All rights reserved.  This program is free software; you can
+redistribute it and/or modify it under the same terms as Perl itself.
+
+=head1 SEE ALSO
+
+L<perl(1)>, L<Net::DNS>, L<Net::DNS::Resolver>, L<Net::DNS::Packet>,
+L<Net::DNS::Header>, L<Net::DNS::Question>, L<Net::DNS::RR>,
+RFC 2435 Section 4
+
+=cut
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/SOA.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/SOA.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/SOA.pm	Sun Nov 19 07:06:06 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/SOA.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::SOA;
 
-# $Id: SOA.pm,v 1.5 2000/11/19 06:05:52 mfuhr Exp mfuhr $
+# $Id: SOA.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -98,6 +99,32 @@
 
 	return $rdata;
 }
+
+
+
+sub _canonicalRdata {
+    my $self=shift;
+    my $rdata = "";
+
+    # Assume that if one field exists, they all exist.  Script will
+    # print a warning otherwise.
+    
+    if (exists $self->{"mname"}) {
+	$rdata .= $self->_name2wire($self->{"mname"});
+	
+	$rdata .=  $self->_name2wire($self->{"rname"});
+
+		$rdata .= pack("N5", $self->{"serial"},
+				     $self->{"refresh"},
+				     $self->{"retry"},
+				     $self->{"expire"},
+				     $self->{"minimum"});
+	}
+
+	return $rdata;
+}
+
+
 
 1;
 __END__
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/SRV.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/SRV.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/SRV.pm	Sun Nov 19 07:06:24 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/SRV.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::SRV;
 
-# $Id: SRV.pm,v 1.5 2000/11/19 06:06:11 mfuhr Exp mfuhr $
+# $Id: SRV.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -65,6 +66,20 @@
 				     $self->{"port"});
 		$rdata .= $packet->dn_comp($self->{"target"},
 					   $offset + length $rdata);
+	}
+
+	return $rdata;
+}
+
+
+sub _canonicalRdata {
+    my $self=shift;
+    my $rdata = "";
+    
+    if (exists $self->{"priority"}) {
+	$rdata .= pack("n3", $self->{"priority"}, $self->{"weight"},
+		       $self->{"port"});
+	$rdata .= $self->name_2wire($self->{"target"});
 	}
 
 	return $rdata;
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/TSIG.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/TSIG.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/TSIG.pm	Wed Feb  7 06:16:12 2001
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/TSIG.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,6 @@
 package Net::DNS::RR::TSIG;
 
-# $Id: TSIG.pm,v 1.7 2001/02/07 05:16:05 mfuhr Exp mfuhr $
+# $Id: TSIG.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
 
 use strict;
 use vars qw(@ISA);
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/TXT.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/TXT.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/TXT.pm	Sun Nov 19 07:07:48 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/TXT.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::TXT;
 
-# $Id: TXT.pm,v 1.6 2000/11/19 06:07:41 mfuhr Exp mfuhr $
+# $Id: TXT.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -29,7 +30,7 @@
 
 	if ($string && $string =~ /^\s*["']?(.*?)["']?\s*$/) {
 		$self->{"txtdata"} = $1;
-	}
+	}  #'
 
 	return bless $self, $class;
 }
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR/X25.pm Net-DNS-0.19.patched/lib/Net/DNS/RR/X25.pm
--- Net-DNS-0.19/lib/Net/DNS/RR/X25.pm	Sun Nov 19 07:07:58 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR/X25.pm	Mon Apr 23 13:05:02 2001
@@ -1,6 +1,7 @@
 package Net::DNS::RR::X25;
 
-# $Id: X25.pm,v 1.6 2000/11/19 06:07:51 mfuhr Exp mfuhr $
+# $Id: X25.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 
 use strict;
 use vars qw(@ISA);
@@ -26,7 +27,7 @@
 sub new_from_string {
 	my ($class, $self, $string) = @_;
 
-	if ($string && $string =~ /^\s*["']?(.*?)["']?\s*$/) {
+	if ($string && $string =~ /^\s*["']?(.*?)["']?\s*$/) {  #'
 		$self->{"psdn"} = $1;
 	}
 
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/RR.pm Net-DNS-0.19.patched/lib/Net/DNS/RR.pm
--- Net-DNS-0.19/lib/Net/DNS/RR.pm	Wed Feb  7 06:15:41 2001
+++ Net-DNS-0.19.patched/lib/Net/DNS/RR.pm	Mon Apr 23 13:05:02 2001
@@ -6,7 +6,9 @@
 use Carp;
 use Net::DNS;
 
-# $Id: RR.pm,v 1.15 2001/02/07 05:15:30 mfuhr Exp mfuhr $
+
+# $Id: RR.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 $VERSION = $Net::DNS::VERSION;
 
 =head1 NAME
@@ -61,6 +63,10 @@
 use Net::DNS::RR::TSIG;		$RR{"TSIG"}	= 1;
 use Net::DNS::RR::TXT;		$RR{"TXT"}	= 1;
 use Net::DNS::RR::X25;		$RR{"X25"}	= 1;
+use Net::DNS::RR::NXT;		$RR{"NXT"}	= 1;
+use Net::DNS::RR::KEY;		$RR{"KEY"}	= 1;
+use Net::DNS::RR::SIG;		$RR{"SIG"}	= 1;
+use Net::DNS::RR::OPT;		$RR{"OPT"}	= 1;
 
 =head2 new (from string)
 
@@ -263,12 +269,12 @@
 }
 
 sub new_from_hash {
-	my $class = shift;
+        my $class = shift;
 	my %tempself = @_;
 	my (%self, $retval);
 	my ($key, $val);
 
-	while (($key, $val) = each %tempself) {
+       	while (($key, $val) = each %tempself) {
 		$self{lc($key)} = $val;
 	}
 
@@ -278,20 +284,24 @@
 		unless exists $self{"type"};
 
 	$self{"ttl"}   = 0    unless exists $self{"ttl"};
-	$self{"class"} = "IN" unless exists $self{"class"};
+	$self{"class"} = "IN" unless exists $self{"class"}; 
 
 	$self{"rdlength"} = length $self{"rdata"}
 		if exists $self{"rdata"};
-
-	if ($RR{$self{"type"}}) {
-		my $subclass = $class . "::" . $self{"type"};
+	
+	if ($RR{uc $self{"type"}}) {
+	    my $subclass = $class . "::" . uc $self{"type"};
+	    if (uc $self{"type"} ne "OPT"){
 		$retval = bless \%self, $subclass;
+	    }else{  # Special processing of OPT. Since TTL and CLASS are
+		    # set by other variables. See Net::DNS::RR::OPT 
+                    # documentation
+		$retval = $subclass->new_from_hash(\%self);
+	    }
+	}else {
+	    $retval = bless \%self, $class;
 	}
-	else {
-		$retval = bless \%self, $class;
-	}
-
-	return $retval;
+    return $retval;
 }
 
 #
@@ -311,7 +321,7 @@
 
 sub print {
 	my $self = shift;
-	print $self->string, "\n";
+	print  $self->string, "\n";
 }
 
 =head2 string
@@ -321,12 +331,12 @@
 Returns a string representation of the RR.  Calls the
 B<rdatastr> method to get the RR-specific data.
 
-=cut
+=cut 
+#'
 
 sub string {
-	my $self = shift;
-
-	return $self->{"name"}  . ".\t" .
+    my $self = shift;
+        return $self->{"name"}  . ".\t" .
 	       $self->{"ttl"}   . "\t"  .
 	       $self->{"class"} . "\t"  .
 	       $self->{"type"}  . "\t"  .
@@ -406,6 +416,8 @@
 
 =cut
 
+#'
+
 sub rdata {
 	my $self = shift;
 	my $retval = undef;
@@ -437,6 +449,16 @@
 	my ($self, $packet, $offset) = @_;
 	my $data;
 
+
+	# If the type is OPT then class will need to contain a decimal number
+	# containing the UDP payload size. (RFC2671 section 4.3)
+	# Furhter handled in the data method
+	if (uc($self->{"type"}) ne "OPT"){
+	    $data .= pack("n", $Net::DNS::classesbyname{uc($self->{"class"})});
+	} else
+	{
+	    $data .= pack("n", $self->{"class"});
+	}
 	# Don't compress TSIG names.
 	if (uc($self->{"type"}) eq "TSIG") {
 		my $tmp_packet = Net::DNS::Packet->new("");
@@ -457,7 +479,7 @@
 	$data .= pack("n", $qtype_val);
 	$data .= pack("n", $qclass_val);
 	$data .= pack("N", $self->{"ttl"});
-
+	
 	$offset += length($data) + &Net::DNS::INT16SZ;	# allow for rdlength
 
 	my $rdata = $self->rdata($packet, $offset);
@@ -468,6 +490,67 @@
 	return $data;
 }
 
+
+
+#------------------------------------------------------------------------------
+#  This method is called by SIG objects verify method. 
+#  It is almost the same as data but needed to get an representation of the
+#  packets in wire format withoud domain name compression.
+#  It is essential to DNSSEC RFC 2535 section 8
+#------------------------------------------------------------------------------
+
+sub _canonicaldata {
+    my $self = shift;
+    my $data="";
+    {   my @dname= split /\./,lc($self->{"name"});
+	for (my $i=0;$i<@dname;$i++){
+	    $data .= pack ("C",length $dname[$i] );
+	    $data .= $dname[$i] ;
+	}
+	$data .= pack ("C","0");
+    }
+    $data .= pack("n", $Net::DNS::typesbyname{uc($self->{"type"})});
+    $data .= pack("n", $Net::DNS::classesbyname{uc($self->{"class"})});
+    $data .= pack("N", $self->{"ttl"});
+    
+    
+    my $rdata = $self->_canonicalRdata;
+
+    $data .= pack("n", length $rdata);
+    $data .= $rdata;
+    return $data;
+
+
+}
+
+# These are methods that are used in the DNSSEC context...  Some RR
+# have domain names in them. Verification works only on RRs with
+# uncompressed domain names. (Canonical format as in sect 8 of
+# RFC2535) _canonicalRdata is overwritten in those RR objects that
+# have domain names in the RDATA and _name2label is used to convert a
+# domain name to "wire format"
+
+sub _canonicalRdata {
+    my $self = shift;
+    my $rdata = $self->rr_rdata;
+    return $rdata;
+}
+
+
+
+sub _name2wire   {   
+    my ($self,$name)=@_;
+
+    my $rdata="";
+    my @dname= split /\./,lc($name);
+    for (my $i=0;$i<@dname;$i++){
+	$rdata .= pack ("C",length $dname[$i] );
+	$rdata .= $dname[$i] ;
+    }
+    $rdata .= pack ("C","0");
+    return $rdata;
+}
+
 sub AUTOLOAD {
 	my $self = shift;
 	my $name = $AUTOLOAD;
@@ -511,6 +594,9 @@
 Copyright (c) 1997-2000 Michael Fuhr.  All rights reserved.  This
 program is free software; you can redistribute it and/or modify it
 under the same terms as Perl itself. 
+
+
+Some DNSSEC/EDNS functionality added by  Olaf M. Kolkman, RIPE NCC.
 
 =head1 SEE ALSO
 
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Resolver.pm Net-DNS-0.19.patched/lib/Net/DNS/Resolver.pm
--- Net-DNS-0.19/lib/Net/DNS/Resolver.pm	Tue Dec 12 09:54:16 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/Resolver.pm	Mon Apr 23 13:05:03 2001
@@ -34,7 +34,7 @@
 
 A space-separated list of domains to put in the search list.
 
-=item B<nameserver>
+item B<nameserver>
 
 A space-separated list of nameservers to query.
 
@@ -49,6 +49,9 @@
 
 =cut
 
+#'
+
+
 use Config;
 use FileHandle;
 use strict;
@@ -86,7 +89,8 @@
 eval "use Time::HiRes";
 $can_time = $@ ? 0 : 1;
 
-# $Id: Resolver.pm,v 1.18 2000/12/08 01:02:41 mfuhr Exp mfuhr $
+# $Id: Resolver.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
+
 $VERSION = $Net::DNS::VERSION;
 
 #------------------------------------------------------------------------------
@@ -125,6 +129,9 @@
 	"axfr_rr"        => [],
 	"axfr_soa_count" => 0,
 	"persistent_tcp" => 0,
+        "dnssec"        => 0,
+        "udppacketsize" => 0,  # The actual default is lower bound by Net::DNS::PACKETSZ
+        "cdflag"      => 1,    # this is only used when {dnssec}==1
 );
 
 %global = (
@@ -304,7 +311,7 @@
 Returns a string representation of the resolver state.
 
 =cut
-
+#"
 sub string {
 	my $self = shift;
 
@@ -325,7 +332,14 @@
 		";;  defnames = $self->{defnames}  "		.
 		"dnsrch   = $self->{dnsrch}\n"			.
 		";;  recurse  = $self->{recurse}  "		.
-		"debug    = $self->{debug}\n";
+		"debug    = $self->{debug}\n"                   .
+                ";;   dnssec  = $self->{dnssec}  "        	.
+		 (( $self->{dnssec} ) ?	  "cdflag = ".$self->{cdflag} ."\n"
+		  : "\n" );
+	    ( ( $self->{"udppacketsize"} > &Net::DNS::PACKETSZ ) ?  
+	      "\n;; EDNS udppacketsize " . $self->{"udppacketsize"} . "\n"
+	      : 
+	      "\n" ) ;
 }
 
 sub nextid {
@@ -546,7 +560,7 @@
 were found.
 
 =cut
-
+#"
 sub query {
 	my ($self, $name, $type, $class) = @_;
 
@@ -557,18 +571,47 @@
 	if ((index($name, ".") < 0) && $self->{"defnames"}) {
 		$name .= ".$self->{domain}";
 	}
-
+ 
 	# If the name looks like an IP address then do an appropriate
 	# PTR query.
-	if ($name =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
+ 	if ($name =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) {
 		$name = "$4.$3.$2.$1.in-addr.arpa";
 		$type = "PTR";
+	} 
+
+	print ";; query($name, $type, $class)\n" if $self->{"debug"}; 
+	my $packet = new Net::DNS::Packet($name, $type, $class);  
+
+	if ($self->{"dnssec"}){
+	    print ";; Adding EDNS extention with UDP packetsize ".
+		$self->{"udppacketsize"}." and DNS OK bit set\n" if $self->{"debug"};
+	    # draft-ietf-dnsext-dnssec-okbit-01.txt
+	    my $optrr = 
+		new Net::DNS::RR(
+				 Type         => "OPt",
+				 Name         => "",
+				 Class        => $self->{"udppacketsize"},  # Decimal UDPpayload
+				 ednsflags     => 0x8000, # first bit set see draft-ietf-dnsext-dnssec-okbit-01.txt
+
+				 );
+	    $packet->push("additional",$optrr);
+	}
+	elsif( $self->{"udppacketsize"} > &Net::DNS::PACKETSZ ){
+	    print ";; Adding EDNS extention with UDP packetsize ".
+		$self->{"udppacketsize"}." \n" if $self->{"debug"};
+	    # draft-ietf-dnsext-dnssec-okbit-01.txt
+	    my $optrr = 
+		new Net::DNS::RR(
+				 Type         => "OPt",
+				 Name         => "",
+				 Class        => $self->{"udppacketsize"},  # Decimal UDPpayload
+				 TTL          => 0x0000 # RCODE 32bit Hex
+				 );
+	    $packet->push("additional",$optrr);
 	}
 
-	print ";; query($name, $type, $class)\n" if $self->{"debug"};
-	my $packet = Net::DNS::Packet->new($name, $type, $class);
 	my $ans = $self->send($packet);
-
+	
 	return (defined($ans) && ($ans->header->ancount > 0)) ? $ans : undef;
 }
 
@@ -601,7 +644,13 @@
 
 	my $ans;
 
-	if ($self->{"usevc"} || length $packet_data > &Net::DNS::PACKETSZ) {
+	if ($self->{"usevc"} || 
+	    # if ($self->{"udppacketsize"}  > &Net::DNS::PACKETSZ then we use EDNS and
+	    # $self->{"udppacketsize"} should be takedn as the maximum packet_data length
+	   ( length $packet_data >  ($self->{"udppacketsize"} > &Net::DNS::PACKETSZ ? 
+				     $self->{"udppacketsize"} : 
+				     &Net::DNS::PACKETSZ) )
+	    ){
 		$ans = $self->send_tcp($packet, $packet_data);
 	}
 	else {
@@ -813,7 +862,13 @@
 
 			foreach my $ready (@ready) {
 				my $buf = "";
-				if ($ready->recv($buf, &Net::DNS::PACKETSZ)) {
+				if ($ready->recv($buf,  
+				    #If "udppacketsize is larger then &Net::DNS::PACKETSZ 
+				    #EDNS is used and we accept packetsizes of max length
+				    #$self->{"udppacketsize"}
+                                    ($self->{"udppacketsize"} > &Net::DNS::PACKETSZ ? 
+				     $self->{"udppacketsize"} : 
+				     &Net::DNS::PACKETSZ))){
 					$self->answerfrom($ready->peerhost);
 					$self->answersize(length $buf);
 					print ";; answer from ",
@@ -1022,6 +1077,13 @@
 		$packet->header->rd($self->{"recurse"});
 	}
 
+
+	if ($self->{"dnssec"}){
+	    $packet->header->cd($self->{"cdflag"});
+	}else{
+	    $packet->header->cd(0);
+	}
+
 	if ($self->{"tsig_rr"}) {
 		if (!grep { $_->type eq "TSIG" } $packet->additional) {
 			$packet->push("additional", $self->{"tsig_rr"});
@@ -1639,6 +1701,39 @@
 Returns the size in bytes of the last answer we received in
 response to a query.
 
+
+=head2 dnssec
+
+    print "dnssec flag: ", $res->dnssec, "\n";
+    $res->dnssec(0);
+
+Enabled DNSSEC this will set the checking disabled flag in the query header
+and add EDNS0 data as in RFC2671 and draft-ietf-dnsext-dnssec-okbit-01.txt
+
+When set to true the answer and additional section of queries from
+secured zones will contain KEY, NXT and SIG records.
+
+
+=head2 cdflag
+
+    print "checking disabled flag: ", $res->dnssec, "\n";
+    $res->dnssec(1);
+    $res->cdflag(1);
+
+Sets or gets the CD bit for a dnssec query.  This bit is always zero
+for non dnssec queries. When the dnssec is enabled the flag can be set
+to 1.
+
+=head2 udppacketsize
+
+    print "udppacketsize: ", $res->udppacketsize, "\n";
+    $res->udppacketsize(2048);
+
+udppacketsize will set or get the packet size. If set to a value greater than 
+&Net::DNS::PACKETSZ an EDNS extention will be added indicating suppport for MTU path 
+recovery.
+
+Default udppacketsize is &Net::DNS::PACKETSZ (512)
 =cut
 
 sub AUTOLOAD {
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Select.pm Net-DNS-0.19.patched/lib/Net/DNS/Select.pm
--- Net-DNS-0.19/lib/Net/DNS/Select.pm	Fri Nov 10 17:18:47 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/Select.pm	Mon Apr 23 13:05:03 2001
@@ -7,7 +7,7 @@
 use strict;
 use vars qw($VERSION);
 
-# $Id: Select.pm,v 1.1 2000/11/10 16:17:51 mfuhr Exp mfuhr $
+# $Id: Select.pm,v 1.2 2001/04/21 20:21:13 olaf Exp $
 $VERSION = $Net::DNS::Version;
 
 sub new {
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS/Update.pm Net-DNS-0.19.patched/lib/Net/DNS/Update.pm
--- Net-DNS-0.19/lib/Net/DNS/Update.pm	Mon Nov 20 00:55:35 2000
+++ Net-DNS-0.19.patched/lib/Net/DNS/Update.pm	Mon Apr 23 13:05:03 2001
@@ -5,7 +5,8 @@
 
 use Net::DNS;
 
-# $Id: Update.pm,v 1.6 2000/11/19 23:55:28 mfuhr Exp mfuhr $
+
+# $Id: Update.pm,v 1.3 2001/04/21 20:21:13 olaf Exp $
 $VERSION = $Net::DNS::VERSION;
 
 =head1 NAME
diff -B -u --recursive --new-file Net-DNS-0.19/lib/Net/DNS.pm Net-DNS-0.19.patched/lib/Net/DNS.pm
--- Net-DNS-0.19/lib/Net/DNS.pm	Wed Feb  7 06:12:48 2001
+++ Net-DNS-0.19.patched/lib/Net/DNS.pm	Mon Apr 23 13:05:03 2001
@@ -1,6 +1,4 @@
 package Net::DNS;
-# $Id: DNS.pm,v 1.20 2001/02/07 05:12:43 mfuhr Exp mfuhr $
-
 require 5.6.0;
 
 use strict;
@@ -8,6 +6,7 @@
 	$VERSION
 	@ISA
 	@EXPORT
+	@EXPORT_OK
 	%typesbyname
 	%typesbyval
 	%classesbyname
@@ -18,7 +17,8 @@
 	%rcodesbyval
 );
 
-$VERSION = "0.19";
+$VERSION = "0.19-DNSSEC";
+
 
 use Net::DNS::Resolver;
 use Net::DNS::Packet;
@@ -56,9 +56,9 @@
 	"RT"		=> 21,		# RFC 1183, Section 3.3
 	"NSAP"		=> 22,		# RFC 1706, Section 5
 	"NSAP_PTR"	=> 23,		# RFC 1348 (obsolete)
-	"SIG"		=> 24,		# RFC 2535
-	"KEY"		=> 25,		# RFC 2535
-	"PX"		=> 26,		# RFC 2163
+	"SIG"		=> 24,		# RFC 2555, Section 4.1
+	"KEY"		=> 25,		# RFC 2565, Section 3.1
+	"PX"		=> 26,		# RFC 2163,
 	"GPOS"		=> 27,		# RFC 1712 (obsolete)
 	"AAAA"		=> 28,		# RFC 1886, Section 2.1
 	"LOC"		=> 29,		# RFC 1876
@@ -404,6 +404,10 @@
 Many of the examples are intentionally simple and don't do things
 like follow CNAME records.  Such code is left as an exercise for
 the reader.
+
+See the C<Net::DNS::Update> manual page for an example of performing
+dynamic updates.
+
 
 See the C<Net::DNS::Update> manual page for examples of performing
 dynamic updates.  RFC 2136 describes dynamic updates.

Home | Date list | Subject list