Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 15798
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: OLAF [...] cpan.org
Requestors: bugs [...] jth.net
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.53
Fixed in: (no value)



Subject: Bugs in TXT handling
1) In RR.pm semicolons in the TXT data are considered as start of comment which they should not. ... TXT "abc;def" will be truncated to ... TXT "abc with open quotes. Escaping \; will result in ... TXT "abc\\\;def" Could be fixed as shown provided the rdata is enclosed in '' or "" with no comments. (Why be concerned with comments in the input anyway ? Strange. ) # strip out comments # Test for non escaped ";" by means of the look-behind assertion # (the backslash is escaped) $rrstring =~ s/(?<!\\);[^"']*$//g; 2) Creating a TXT record by hash does not work. rdata => '....' does not get recognized. - Jørgen Thomsen Perl 5.8.7
[guest - Mon Nov 14 17:45:50 2005]: Show quoted text
> 1) In RR.pm semicolons in the TXT data are considered as start of > comment which they should not.
The RR.pm takes "zonefile format" as input. In a zonefile a semicolon is defined as the start of a comment. Net::DNS::RR->new ( "net-dns.org. 3600 IN SOA ns1.net-dns.org. olaf.dacht.net. ( 2005092303 ; serial 450 ; refresh (7 minutes 30 seconds) 600 ; retry (10 minutes) 345600 ; expire (4 days) 300 ; minimum (5 minutes) ) "); is therefore perfectly valid input. (makes easy cut and paste). Having said that the interaction in TXT RRs is somewhat troublesome. Note that a TXT RR is made out of several character strings, that even further complicates matters. Show quoted text
> ... TXT "abc;def" > will be truncated to > ... TXT "abc > with open quotes. > Escaping \; will result in > ... TXT "abc\\\;def" > > Could be fixed as shown provided the rdata is enclosed in '' or "" > with no comments. (Why be concerned with comments in the input > anyway ? Strange. )
I think the comments are useful in general. The trick here is to use single quotes (and still escape the ;. See e.g. t/07-misc.t: my $TXTrr2=Net::DNS::RR->new('txt2.t.net-dns.org. 60 IN TXT "Test1 \" \; more stuff" "Test2"'); is(($TXTrr2->char_str_list())[0],'Test1 " ; more stuff', "First arg string in TXT RR read from zonefileformat"); is(($TXTrr2->char_str_list())[1],'Test2',"Second Char string in TXT RR read from zonefileformat"); Also see ticket 8803. Show quoted text
> 2) Creating a TXT record by hash does not work. rdata => '....' does > not get recognized.
There is no such attribute as rdata. If you want to fill the datastructure directly using a hash you probably have to use the char_str_list => [<anonymous hash of character strings>] construct. --Olaf
I've added the chapter below to the perlpod. I will close the ticket, feel free to reopen it if you have specific suggestions on how to do this better. --Olaf =head1 Features The RR.pm module accepts semi-colons as a start of a comment. This is to allow the RR.pm to deal with RFC1035 specified zonefile format. For some applications of the TXT RR the semicolon is relevant, you will need to escape it on input. Also note that you should specify the several character strings seperatly. The easiest way to do so is to include the whole argument in single quotes and the several character strings in double quotes. Double quotes inside the character strings will need to be escaped. my $TXTrr=Net::DNS::RR->new('txt2.t.net-dns.org. 60 IN TXT "Test1 \" \; more stuff" "Test2"'); would result in $TXTrr->char_str_list())[0] containing 'Test1 " ; more stuff' and $TXTrr->char_str_list())[1] containing 'Test2'
From: bugs [...] jth.net
Show quoted text
> There is no such attribute as rdata. If you want to fill the > datastructure directly using a hash > you probably have to use the char_str_list => [<anonymous hash of > character strings>] > construct.
The 'rdata' is mentioned all over in the code, but anyway don't you think it odd having (quoting your documentation) new (from hash) $rr = Net::DNS::RR->new( name => "foo.example.com", ttl => 86400, class => "IN", type => "A", address => "10.1.2.3", ); but not a similar one for TXT data or resource records in general ? - Jørgen Thomsen
From: bugs [...] jth.net
[OLAF - Tue Nov 15 04:03:59 2005]: Show quoted text
> The trick here is to use single quotes (and still escape the ;. > > See e.g. t/07-misc.t: > my $TXTrr2=Net::DNS::RR->new('txt2.t.net-dns.org. 60 IN > TXT "Test1 \" \; more stuff" "Test2"'); > > is(($TXTrr2->char_str_list())[0],'Test1 " ; more stuff', "First arg > string in TXT RR read from > zonefileformat"); > is(($TXTrr2->char_str_list())[1],'Test2',"Second Char string in TXT RR > read from > zonefileformat"); >
You didn't test this against a real running BIND server, right ? TXT "\"Test1 \" \\\; more stuff\" \"Test2\"" is not exactly what is wanted. - Jørgen Thomsen
I am affraid I do not exactly understand how you tested against a bind server. I also do not understand what produces the output you provided with all the backslashes. As for the new_from_hash method you want to use the char_str_list. Some example code is below. In order to show that this is wire compatible with BIND I set up a perl nameserver and use dig to query it. First the code: ------------------- cut --------------------- #!/usr/local/bin/perl -Wall use strict; use warnings; use Net::DNS::Nameserver; my $nameserver=Net::DNS::Nameserver->new ( LocalAddr => "127.0.0.1", LocalPort => 3553, Verbose => 1, ReplyHandler => \&reply_handler, ); my $rr = Net::DNS::RR->new( name => "foo.example.com", ttl => 86400, class => "IN", type => "TXT", char_str_list => ['bla',';'], ); my $rr2=Net::DNS::RR->new('foo2.example.com 600 IN TXT "Test1 \" \; more stuff" "Test2"'); $rr->print; $rr2->print; sub reply_handler { my ($qname, $qclass, $qtype, $peerhost) = @_; my ($rcode, @ans, @auth, @add); if ($qtype eq "TXT" && $qname eq "foo.example.com") { push @ans, $rr; }elsif ($qtype eq "TXT" && $qname eq "foo2.example.com") { push @ans, $rr; } else { $rcode = "SERFAIL"; } return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); } $nameserver->main_loop; ---------------- cut --------------------------------- And these are the queries that return exactly what I think should be returned grover-Secret-Wg-org:~ olaf$ dig @127.0.0.1 -p 3553 foo.example.com TXT ; <<>> DiG 9.3.1 <<>> @127.0.0.1 -p 3553 foo.example.com TXT ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35736 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;foo.example.com. IN TXT ;; ANSWER SECTION: foo.example.com. 86400 IN TXT "bla" "\;" ;; Query time: 197 msec ;; SERVER: 127.0.0.1#3553(127.0.0.1) ;; WHEN: Sat Nov 19 23:43:31 2005 ;; MSG SIZE rcvd: 51 grover-Secret-Wg-org:~ olaf$ dig @127.0.0.1 -p 3553 foo2.example.com TXT ; <<>> DiG 9.3.1 <<>> @127.0.0.1 -p 3553 foo2.example.com TXT ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44794 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;foo2.example.com. IN TXT ;; ANSWER SECTION: foo.example.com. 86400 IN TXT "bla" "\;" ;; Query time: 36 msec ;; SERVER: 127.0.0.1#3553(127.0.0.1) ;; WHEN: Sat Nov 19 23:43:37 2005 ;; MSG SIZE rcvd: 56 I hope this helps... --Olaf
I am affraid I do not exactly understand how you tested against a bind server. I also do not understand what produces the output you provided with all the backslashes. As for the new_from_hash method you want to use the char_str_list. Some example code is below. In order to show that this is wire compatible with BIND I set up a perl nameserver and use dig to query it. First the code: ------------------- cut --------------------- #!/usr/local/bin/perl -Wall use strict; use warnings; use Net::DNS::Nameserver; my $nameserver=Net::DNS::Nameserver->new ( LocalAddr => "127.0.0.1", LocalPort => 3553, Verbose => 1, ReplyHandler => \&reply_handler, ); my $rr = Net::DNS::RR->new( name => "foo.example.com", ttl => 86400, class => "IN", type => "TXT", char_str_list => ['bla',';'], ); my $rr2=Net::DNS::RR->new('foo2.example.com 600 IN TXT "Test1 \" \; more stuff" "Test2"'); $rr->print; $rr2->print; sub reply_handler { my ($qname, $qclass, $qtype, $peerhost) = @_; my ($rcode, @ans, @auth, @add); if ($qtype eq "TXT" && $qname eq "foo.example.com") { push @ans, $rr; }elsif ($qtype eq "TXT" && $qname eq "foo2.example.com") { push @ans, $rr; } else { $rcode = "SERFAIL"; } return ($rcode, \@ans, \@auth, \@add, { aa => 1 }); } $nameserver->main_loop; ---------------- cut --------------------------------- And these are the queries that return exactly what I think should be returned grover-Secret-Wg-org:~ olaf$ dig @127.0.0.1 -p 3553 foo.example.com TXT ; <<>> DiG 9.3.1 <<>> @127.0.0.1 -p 3553 foo.example.com TXT ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 35736 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;foo.example.com. IN TXT ;; ANSWER SECTION: foo.example.com. 86400 IN TXT "bla" "\;" ;; Query time: 197 msec ;; SERVER: 127.0.0.1#3553(127.0.0.1) ;; WHEN: Sat Nov 19 23:43:31 2005 ;; MSG SIZE rcvd: 51 grover-Secret-Wg-org:~ olaf$ dig @127.0.0.1 -p 3553 foo2.example.com TXT ; <<>> DiG 9.3.1 <<>> @127.0.0.1 -p 3553 foo2.example.com TXT ; (1 server found) ;; global options: printcmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44794 ;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;foo2.example.com. IN TXT ;; ANSWER SECTION: foo.example.com. 86400 IN TXT "bla" "\;" ;; Query time: 36 msec ;; SERVER: 127.0.0.1#3553(127.0.0.1) ;; WHEN: Sat Nov 19 23:43:37 2005 ;; MSG SIZE rcvd: 56 I hope this helps... --Olaf
Ooops... Forget my last mail.. $rr2 failed...
Show quoted text
> Ooops... > > Forget my last mail.. $rr2 failed...
There were two small typos --- I should not do this shortly before going to bed ---, the demoscript does work now. Instead of copying it here again it is on www.net-dns.org/txtdemo.pl It runs on ip 127.0.0.1 port 3553 and the two queries it answers to are dig @127.0.0.1 -p 3553 foo.example.com TXT and dig @127.0.0.1 -p 3553 foo2.example.com TXT Note that although we use \; in our input and dig prints \; in its output only the semi-colon character travels the wire. See the ethereal output below for the reply to the foo2.example.com TXT query. (The relevant sequence is 20 22 20 3b 20) 0000 00 00 00 02 45 00 00 65 01 0b 00 00 40 11 00 00 ....E..e ....@... 0010 7f 00 00 01 7f 00 00 01 00 35 ec e9 00 51 fe 64 ........ .5...Q.d 0020 da 5b 85 00 00 01 00 01 00 00 00 00 04 66 6f 6f .[...... .....foo 0030 32 07 65 78 61 6d 70 6c 65 03 63 6f 6d 00 00 10 2.exampl e.com... 0040 00 01 c0 0c 00 10 00 01 00 00 02 58 00 1b 14 54 ........ ...X...T 0050 65 73 74 31 20 22 20 3b 20 6d 6f 72 65 20 73 74 est1 " ; more st 0060 75 66 66 05 54 65 73 74 32 uff.Test 2 Hope this all helps a bit, --Olaf
From: bugs [...] jth.net
[OLAF - Sat Nov 19 17:50:49 2005]: Show quoted text
> > I am affraid I do not exactly understand how you tested against a bind > server. I also do not > understand what produces the output you provided with all the > backslashes. >
$tmp = rr_add("$name $ttl $rrtype '$txt'"); $update->push("update", $tmp); With your code ($rrstring =~ s/(?<!\\);.*//g;) ---- test.demo1.kom 14400 TXT 'abc\;def' ;; ANSWER SECTION: test.demo1.kom. 14400 IN TXT "abc\\\;def" ---- test.demo1.kom 14400 TXT 'abc;def' test.demo1.kom. 14400 IN TXT ; no data Returkode: FORMERR ----- With my code ($rrstring =~ s/(?<!\\);[^"']*$//g;) test1.demo1.kom. 14400 IN TXT "abc\;def" ;; ANSWER SECTION: test1.demo1.kom. 14400 IN TXT "abc\\\;def" ----- test1.demo1.kom 14400 TXT 'abc;def' ;; ANSWER SECTION: test1.demo1.kom. 14400 IN TXT "abc\;def" ----- - Jørgen
From: bugs [...] jth.net
[OLAF - Sat Nov 19 17:50:49 2005]: Show quoted text
> > I am affraid I do not exactly understand how you tested against a bind > server. I also do not > understand what produces the output you provided with all the > backslashes. >
$tmp = rr_add("$name $ttl $rrtype '$txt'"); $update->push("update", $tmp); With your code ($rrstring =~ s/(?<!\\);.*//g;) ---- test.demo1.kom 14400 TXT 'abc\;def' ;; ANSWER SECTION: test.demo1.kom. 14400 IN TXT "abc\\\;def" ---- test.demo1.kom 14400 TXT 'abc;def' test.demo1.kom. 14400 IN TXT ; no data Returkode: FORMERR ----- With my code ($rrstring =~ s/(?<!\\);[^"']*$//g;) test1.demo1.kom. 14400 IN TXT "abc\;def" ;; ANSWER SECTION: test1.demo1.kom. 14400 IN TXT "abc\\\;def" ----- test1.demo1.kom 14400 TXT 'abc;def' ;; ANSWER SECTION: test1.demo1.kom. 14400 IN TXT "abc\;def" ----- - Jørgen
From: "Olaf M. Kolkman" <olaf [...] dacht.net>
Subject: Re: [cpan #15798] Bugs in TXT handling
Date: Sun, 20 Nov 2005 20:25:43 +0100
To: bug-Net-DNS [...] rt.cpan.org
RT-Send-Cc:
Hello Jørgen Aha, I was not aware you were using dynamic updates. In a dynamic update scheme this is what works: my $update2= Net::DNS::Update->new('net-dns.org'); my $name="dynup.net-dns.org"; my $ttl=1; my $rrtype="TXT"; my $txt='"fooFoo2" "Bla \; Foo"'; $update2->push(update =>rr_add("$name $ttl $rrtype $txt")); $update2->push(additional => $tsig); "dig" at the dynamically updated zone gives me: ;; ANSWER SECTION: dynup.net-dns.org. 1 IN TXT "fooFoo2" "Bla \; Foo" The TXT records rdata is two character strings, one containing "fooFoo2" and one "Bla ; Foo". In presentation format the semi colon is escaped. 'dig' prints presentation format. The case with which Net::DNS bails out is if there is an unescaped comment in a character string: $txt=' "foo" " bla ; comment" ' But then again the semicolon is AFAIK a special character that should be escaped as by RFC1035. Anyway I did manage to reconstruct the problem you reported. And it seems to be due by the fact that you put single quotes around $txt in the rr_add argument. you use rr_add("$name $ttl $rrtype '$txt'"); while the for rr_add("$name $ttl $rrtype $txt"); the correct thing happens. Just remember that the formal way to represent TXT RRs is using one or more <character-strings> that are surrounded by double quotes. $txt=' "character-string1" "character-string2" ' I hope this helps. --Olaf ------------------------------------------------------ Ik dacht net... heel even maar.
Download PGP.sig
application/pgp-signature 227b

Message body not shown because it is not plain text.

From: bugs [...] jth.net
[olaf@dacht.net - Sun Nov 20 14:26:25 2005]: Show quoted text
> Anyway I did manage to reconstruct the problem you reported. And it > seems to be due by the fact that you put single quotes around $txt in > the rr_add argument. > > you use rr_add("$name $ttl $rrtype '$txt'"); > while the for rr_add("$name $ttl $rrtype $txt"); >
Quoting from man Net::DNS:RR $txt = Net::DNS::RR->new("baz.example.com 3600 HS TXT 'text record'"); May I suggest updating the documentation. - Jørgen
From: "Olaf M. Kolkman" <olaf [...] dacht.net>
Subject: Re: [cpan #15798] Bugs in TXT handling
Date: Mon, 21 Nov 2005 09:37:53 +0100
To: bug-Net-DNS [...] rt.cpan.org
RT-Send-Cc:
Show quoted text
> > Quoting from man Net::DNS:RR > > $txt = Net::DNS::RR->new("baz.example.com 3600 HS TXT 'text > record'");
Because of your question I already added some explanation to the Net::DNS::RR::TXT documentation. I fixed the Net::DNS::RR and Net::DNS::Update documentation. I'll close the ticket. Thanks for your patience. --Olaf ------------------------------------------------------ Ik dacht net... heel even maar.
Download PGP.sig
application/pgp-signature 227b

Message body not shown because it is not plain text.