ports/116029: backport multiline txt records support
Sten Spans
sten at blinkenlights.nl
Sun Sep 2 20:50:02 UTC 2007
>Number: 116029
>Category: ports
>Synopsis: backport multiline txt records support
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: freebsd-ports-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: maintainer-update
>Submitter-Id: current-users
>Arrival-Date: Sun Sep 02 20:50:01 GMT 2007
>Closed-Date:
>Last-Modified:
>Originator: Sten Spans
>Release: FreeBSD 6.2-RELEASE i386
>Organization:
>Environment:
System: FreeBSD earth.blinkenlights.nl 6.2-RELEASE FreeBSD 6.2-RELEASE #0: Sun Jan 28 15:02:12 CET 2007 root at earth.blinkenlights.nl:/usr/obj/usr/src/sys/1650 i386
>Description:
powerdns-recursor 3.1.4 doesn't support multiline txt records, which
are used by various dns information systems. 3.1.5 does have support
for this.
A backport of the code changes is relatively risk-free, and has been
requested by users and port maintainers.
http://www.nabble.com/recursor-unable-to-resolve-asn.routeviews.org-data-t4252567.html
>How-To-Repeat:
>Fix:
--- Makefile.orig Thu Jun 7 04:24:04 2007
+++ Makefile Sun Sep 2 22:25:53 2007
@@ -7,7 +7,7 @@
PORTNAME= powerdns-recursor
PORTVERSION= 3.1.4
-PORTREVISION= 5
+PORTREVISION= 6
CATEGORIES= dns ipv6
MASTER_SITES= http://downloads.powerdns.com/releases/ \
http://mirrors.evolva.ro/powerdns.com/releases/
--- files/patch-multiline_txt_records Thu Jan 1 01:00:00 1970
+++ files/patch-multiline_txt_records Sun Sep 2 22:23:43 2007
@@ -0,0 +1,398 @@
+Index: dnswriter.hh
+===================================================================
+--- dnswriter.hh (revision 962)
++++ dnswriter.hh (revision 996)
+@@ -84,5 +84,5 @@
+
+ void xfrLabel(const string& label, bool compress=false);
+- void xfrText(const string& text);
++ void xfrText(const string& text, bool multi=false);
+ void xfrBlob(const string& blob);
+ void xfrHexBlob(const string& blob);
+Index: dnsparser.hh
+===================================================================
+--- dnsparser.hh (revision 972)
++++ dnsparser.hh (revision 996)
+@@ -110,7 +110,7 @@
+ }
+
+- void xfrText(string &text)
+- {
+- text=getText();
++ void xfrText(string &text, bool multi=false)
++ {
++ text=getText(multi);
+ }
+
+@@ -126,5 +126,5 @@
+
+ string getLabel(unsigned int recurs=0);
+- string getText();
++ string getText(bool multi);
+
+ uint16_t d_pos;
+Index: zoneparser-tng.cc
+===================================================================
+--- zoneparser-tng.cc (revision 989)
++++ zoneparser-tng.cc (revision 996)
+@@ -281,6 +281,5 @@
+ }
+ catch(...) {
+- cerr<<"Oops, this doesn't look like a qtype, stopping loop\n";
+- break;
++ throw runtime_error("Parsing zone content line: '"+nextpart+"' doesn't look like a qtype, stopping loop");
+ }
+ }
+Index: dnswriter.cc
+===================================================================
+--- dnswriter.cc (revision 962)
++++ dnswriter.cc (revision 996)
+@@ -2,4 +2,5 @@
+ #include "misc.hh"
+ #include "dnsparser.hh"
++#include <boost/tokenizer.hpp>
+
+ DNSPacketWriter::DNSPacketWriter(vector<uint8_t>& content, const string& qname, uint16_t qtype, uint16_t qclass, uint8_t opcode)
+@@ -116,9 +117,20 @@
+ }
+
+-void DNSPacketWriter::xfrText(const string& text)
+-{
+- d_record.push_back(text.length());
+- const uint8_t* ptr=(uint8_t*)(text.c_str());
+- d_record.insert(d_record.end(), ptr, ptr+text.size());
++void DNSPacketWriter::xfrText(const string& text, bool)
++{
++ escaped_list_separator<char> sep('\\', ' ' , '"');
++ tokenizer<escaped_list_separator<char> > tok(text, sep);
++
++ tokenizer<escaped_list_separator<char> >::iterator beg=tok.begin();
++
++ if(beg==tok.end()) {
++ d_record.push_back(0);
++ }
++ else
++ for(; beg!=tok.end(); ++beg){
++ d_record.push_back(beg->length());
++ const uint8_t* ptr=(uint8_t*)(beg->c_str());
++ d_record.insert(d_record.end(), ptr, ptr+beg->length());
++ }
+ }
+
+Index: dnsparser.cc
+===================================================================
+--- dnsparser.cc (revision 972)
++++ dnsparser.cc (revision 996)
+@@ -359,14 +359,42 @@
+ }
+
+-string PacketReader::getText()
++static string txtEscape(const string &name)
++{
++ string ret;
++
++ for(string::const_iterator i=name.begin();i!=name.end();++i)
++ if(*i=='"' || *i=='\\'){
++ ret += '\\';
++ ret += *i;
++ }
++ else
++ ret += *i;
++ return ret;
++}
++
++// exceptions thrown here do not result in logging in the main pdns auth server - just so you know!
++string PacketReader::getText(bool multi)
+ {
+ string ret;
+ ret.reserve(40);
+-
+- unsigned char labellen=d_content.at(d_pos++);
+- ret.append(&d_content.at(d_pos), &d_content.at(d_pos+labellen-1)+1); // the end is one beyond the packet
+- d_pos+=labellen;
+- return ret;
+-}
++ while(d_pos < d_startrecordpos + d_recordlen ) {
++ if(!ret.empty()) {
++ ret.append(1,' ');
++ }
++ unsigned char labellen=d_content.at(d_pos++);
++
++ ret.append(1,'"');
++ string val(&d_content.at(d_pos), &d_content.at(d_pos+labellen-1)+1);
++
++ ret.append(txtEscape(val)); // the end is one beyond the packet
++ ret.append(1,'"');
++ d_pos+=labellen;
++ if(!multi)
++ break;
++ }
++
++ return ret;
++}
++
+
+ void PacketReader::getLabelFromContent(const vector<uint8_t>& content, uint16_t& frompos, string& ret, int recurs)
+Index: rcpgenerator.hh
+===================================================================
+--- rcpgenerator.hh (revision 802)
++++ rcpgenerator.hh (revision 996)
+@@ -51,5 +51,5 @@
+
+ void xfrLabel(string& val, bool compress=false);
+- void xfrText(string& val);
++ void xfrText(string& val, bool multi=false);
+ void xfrHexBlob(string& val);
+ void xfrBlob(string& val);
+@@ -76,5 +76,5 @@
+ void xfrType(const uint16_t& val);
+ void xfrLabel(const string& val, bool compress=false);
+- void xfrText(const string& val);
++ void xfrText(const string& val, bool multi=false);
+ void xfrBlob(const string& val);
+ void xfrHexBlob(const string& val);
+Index: dnsrecords.cc
+===================================================================
+--- dnsrecords.cc (revision 823)
++++ dnsrecords.cc (revision 996)
+@@ -1,5 +1,5 @@
+ /*
+ PowerDNS Versatile Database Driven Nameserver
+- Copyright (C) 2005 - 2006 PowerDNS.COM BV
++ Copyright (C) 2005 - 2007 PowerDNS.COM BV
+
+ This program is free software; you can redistribute it and/or modify
+@@ -178,6 +178,6 @@
+ boilerplate_conv(PTR, ns_t_ptr, conv.xfrLabel(d_content, true));
+ boilerplate_conv(CNAME, ns_t_cname, conv.xfrLabel(d_content, true));
+-boilerplate_conv(TXT, ns_t_txt, conv.xfrText(d_text));
+-boilerplate_conv(SPF, 99, conv.xfrText(d_text));
++boilerplate_conv(TXT, ns_t_txt, conv.xfrText(d_text, true));
++boilerplate_conv(SPF, 99, conv.xfrText(d_text, true));
+ boilerplate_conv(HINFO, ns_t_hinfo, conv.xfrText(d_cpu); conv.xfrText(d_host));
+
+@@ -199,4 +199,9 @@
+ conv.xfr16BitInt(d_preference);
+ conv.xfrLabel(d_mxname, true);
++ )
++
++boilerplate_conv(AFSDB, ns_t_afsdb,
++ conv.xfr16BitInt(d_subtype);
++ conv.xfrLabel(d_hostname);
+ )
+
+@@ -235,4 +240,11 @@
+ conv.xfr32BitInt(d_st.expire);
+ conv.xfr32BitInt(d_st.minimum);
++ );
++#undef KEY
++boilerplate_conv(KEY, ns_t_key,
++ conv.xfr16BitInt(d_flags);
++ conv.xfr8BitInt(d_protocol);
++ conv.xfr8BitInt(d_algorithm);
++ conv.xfrBlob(d_certificate);
+ );
+
+@@ -294,7 +306,9 @@
+ void reportOtherTypes()
+ {
++ AFSDBRecordContent::report();
+ SPFRecordContent::report();
+ NAPTRRecordContent::report();
+ RPRecordContent::report();
++ KEYRecordContent::report();
+ DNSKEYRecordContent::report();
+ RRSIGRecordContent::report();
+Index: dnsrecords.hh
+===================================================================
+--- dnsrecords.hh (revision 823)
++++ dnsrecords.hh (revision 978)
+@@ -196,4 +196,26 @@
+ string d_fingerprint;
+ };
++
++class KEYRecordContent : public DNSRecordContent
++{
++public:
++ includeboilerplate(KEY)
++
++private:
++ uint16_t d_flags;
++ uint8_t d_protocol, d_algorithm;
++ string d_certificate;
++};
++
++class AFSDBRecordContent : public DNSRecordContent
++{
++public:
++ includeboilerplate(AFSDB)
++
++private:
++ uint16_t d_subtype;
++ string d_hostname;
++};
++
+
+ class CERTRecordContent : public DNSRecordContent
+Index: rcpgenerator.cc
+===================================================================
+--- rcpgenerator.cc (revision 850)
++++ rcpgenerator.cc (revision 996)
+@@ -67,9 +67,38 @@
+ if(!isdigit(d_string.at(d_pos)))
+ throw RecordTextException("while parsing IP address, expected digits at position "+lexical_cast<string>(d_pos)+" in '"+d_string+"'");
+-
+- string ip;
+- xfrLabel(ip);
+- if(!IpToU32(ip, &val))
+- throw RecordTextException("unable to parse IP address '"+ip+"'");
++
++ uint32_t octet=0;
++ val=0;
++ char count=0;
++
++ for(;;) {
++ if(d_string.at(d_pos)=='.') {
++ val<<=8;
++ val+=octet;
++ octet=0;
++ count++;
++ if(count > 3)
++ break;
++ }
++ else if(isdigit(d_string.at(d_pos))) {
++ octet*=10;
++ octet+=d_string.at(d_pos) - '0';
++ if(octet > 255)
++ throw RecordTextException("unable to parse IP address");
++ }
++ else if(dns_isspace(d_string.at(d_pos)))
++ break;
++ else
++ throw RecordTextException("unable to parse IP address, strange character: "+d_string.at(d_pos));
++
++ d_pos++;
++ if(d_pos == d_string.length())
++ break;
++ }
++ if(count<=3) {
++ val<<=8;
++ val+=octet;
++ }
++ val=ntohl(val);
+ }
+
+@@ -178,23 +207,31 @@
+ }
+
+-
+-void RecordTextReader::xfrText(string& val)
+-{
+- skipSpaces();
+- if(d_string[d_pos]!='"')
+- throw RecordTextException("Data field in DNS should start with quote (\") at position "+lexical_cast<string>(d_pos)+" of '"+d_string+"'");
+-
++void RecordTextReader::xfrText(string& val, bool multi)
++{
+ val.clear();
+ val.reserve(d_end - d_pos);
+-
+- while(++d_pos < d_end && d_string[d_pos]!='"') {
+- if(d_string[d_pos]=='\\' && d_pos+1!=d_end) {
+- ++d_pos;
++
++ while(d_pos != d_end) {
++ if(!val.empty())
++ val.append(1, ' ');
++
++ skipSpaces();
++ if(d_string[d_pos]!='"')
++ throw RecordTextException("Data field in DNS should start with quote (\") at position "+lexical_cast<string>(d_pos)+" of '"+d_string+"'");
++
++ val.append(1, '"');
++ while(++d_pos < d_end && d_string[d_pos]!='"') {
++ if(d_string[d_pos]=='\\' && d_pos+1!=d_end) {
++ val.append(1, d_string[d_pos++]);
++ }
++ val.append(1, d_string[d_pos]);
+ }
+- val.append(1, d_string[d_pos]);
+- }
+- if(d_pos == d_end)
+- throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'");
+- d_pos++;
++ val.append(1,'"');
++ if(d_pos == d_end)
++ throw RecordTextException("Data field in DNS should end on a quote (\") in '"+d_string+"'");
++ d_pos++;
++ if(!multi)
++ break;
++ }
+ }
+
+@@ -251,11 +288,28 @@
+
+ char tmp[17];
+- snprintf(tmp, sizeof(tmp)-1, "%u.%u.%u.%u",
+- (val >> 24)&0xff,
+- (val >> 16)&0xff,
+- (val >> 8)&0xff,
+- (val )&0xff);
+-
+- d_string+=tmp;
++ uint32_t ip=htonl(val);
++ uint8_t vals[4];
++
++ memcpy(&vals[0], &ip, sizeof(ip));
++
++ char *pos=tmp;
++
++ for(int n=0; n < 4; ++n) {
++ if(vals[n]<10) {
++ *(pos++)=vals[n]+'0';
++ } else if(vals[n] < 100) {
++ *(pos++)=(vals[n]/10) +'0';
++ *(pos++)=(vals[n]%10) +'0';
++ } else {
++ *(pos++)=(vals[n]/100) +'0';
++ vals[n]%=100;
++ *(pos++)=(vals[n]/10) +'0';
++ *(pos++)=(vals[n]%10) +'0';
++ }
++ if(n!=3)
++ *(pos++)='.';
++ }
++ *pos=0;
++ d_string.append(tmp, pos);
+ }
+
+@@ -338,23 +392,10 @@
+ }
+
+-void RecordTextWriter::xfrText(const string& val)
+-{
+- if(!d_string.empty())
+- d_string.append(1,' ');
+- d_string.append(1,'"');
+-
+- if(val.find_first_of("\\\"") == string::npos)
+- d_string+=val;
+- else {
+- string::size_type end=val.size();
+-
+- for(string::size_type pos=0; pos < end; ++pos) {
+- if(val[pos]=='\'' || val[pos]=='"')
+- d_string.append(1,'\\');
+- d_string.append(1, val[pos]);
+- }
+- }
+-
+- d_string.append(1,'"');
++void RecordTextWriter::xfrText(const string& val, bool multi)
++{
++ if(!d_string.empty())
++ d_string.append(1,' ');
++
++ d_string.append(val);
+ }
+
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-ports-bugs
mailing list