--- 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 + + DNSPacketWriter::DNSPacketWriter(vector& 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 sep('\\', ' ' , '"'); ++ tokenizer > tok(text, sep); ++ ++ tokenizer >::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& 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(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(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(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); + } +