File pdns-recursor-3.1.7.2.patch of Package pdns-recursor
--- pdns-recursor-3.1.7/dnsparser.cc
+++ pdns-recursor-3.1.7/dnsparser.cc
@@ -75,20 +75,38 @@
vector<uint8_t> d_record;
};
-static const string EncodeDNSLabel(const string& input)
+static const string EncodeDNSLabel(const string& input)
{
- typedef vector<string> parts_t;
- parts_t parts;
- stringtok(parts,input,".");
- string ret;
- for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
- ret.append(1,(char)i->length());
- ret.append(*i);
- }
- ret.append(1,(char)0);
- return ret;
+ if(input.length() == 1 && input[0]=='.') // otherwise we encode .. (long story)
+ return string (1, 0);
+
+ labelparts_t parts;
+ bool unescapedSomething = labeltokUnescape(parts, input);
+ string ret;
+
+ if(!unescapedSomething) {
+ for(labelparts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
+ ret.append(1, i->second - i->first);
+ ret.append(input.c_str() + i->first, i->second - i->first);
+ }
+
+ } else {
+ for(labelparts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
+ string part(input.c_str() + i->first, i->second - i->first);
+ boost::replace_all(part, "\\\\", "\\");
+ boost::replace_all(part, "\\.", ".");
+
+ ret.append(1, part.length());
+ ret.append(part);
+ }
+ }
+ ret.append(1, 0);
+ // cerr<<"Asked to encode '"<<input<<"', returning: '"<<makeHexDump(ret)<<endl;
+ // cerr<<"parts length: "<<parts.size()<<endl;
+ return ret;
}
+
shared_ptr<DNSRecordContent> DNSRecordContent::unserialize(const string& qname, uint16_t qtype, const string& serialized)
{
dnsheader dnsheader;
@@ -437,7 +455,7 @@
// XXX FIXME THIS MIGHT BE VERY SLOW!
ret.reserve(ret.size() + labellen + 2);
for(string::size_type n = 0 ; n < labellen; ++n, frompos++) {
- if(content.at(frompos)=='.')
+ if(content.at(frompos)=='.' || content.at(frompos)=='\\')
ret.append(1, '\\');
ret.append(1, content[frompos]);
}
--- pdns-recursor-3.1.7/dnsparser.hh
+++ pdns-recursor-3.1.7/dnsparser.hh
@@ -194,7 +194,7 @@
static uint16_t TypeToNumber(const string& name)
{
for(namemap_t::const_iterator i=getNamemap().begin(); i!=getNamemap().end();++i)
- if(!Utility::strcasecmp(i->second.c_str(), name.c_str()))
+ if(pdns_iequals(i->second,name))
return i->first.second;
throw runtime_error("Unknown DNS type '"+name+"'");
--- pdns-recursor-3.1.7/dnswriter.cc
+++ pdns-recursor-3.1.7/dnswriter.cc
@@ -67,7 +67,7 @@
d_stuff = 0;
d_rollbackmarker=d_content.size();
- if(iequals(d_qname,d_recordqname)) { // don't do the whole label compression thing if we *know* we can get away with "see question"
+ if(pdns_iequals(d_qname,d_recordqname)) { // don't do the whole label compression thing if we *know* we can get away with "see question"
static char marker[2]={0xc0, 0x0c};
d_content.insert(d_content.end(), &marker[0], &marker[2]);
}
@@ -153,14 +153,12 @@
{
DNSPacketWriter::lmap_t::iterator ret;
for(ret=lmap.begin(); ret != lmap.end(); ++ret)
- if(iequals(ret->first,label))
+ if(pdns_iequals(ret->first,label))
break;
return ret;
}
-typedef vector<pair<string::size_type, string::size_type> > parts_t;
-
-bool labeltokUnescape(parts_t& parts, const string& label)
+bool labeltokUnescape(labelparts_t& parts, const string& label)
{
string::size_type epos = label.size(), lpos(0), pos;
bool unescapedSomething = false;
@@ -188,7 +186,7 @@
// this is the absolute hottest function in the pdns recursor
void DNSPacketWriter::xfrLabel(const string& label, bool compress)
{
- parts_t parts;
+ labelparts_t parts;
if(label.size()==1 && label[0]=='.') { // otherwise we encode '..'
d_record.push_back(0);
@@ -200,7 +198,7 @@
// d_stuff is amount of stuff that is yet to be written out - the dnsrecordheader for example
unsigned int pos=d_content.size() + d_record.size() + d_stuff;
string chopped;
- for(parts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
+ for(labelparts_t::const_iterator i=parts.begin(); i!=parts.end(); ++i) {
chopped.assign(label.c_str() + i->first);
lmap_t::iterator li=d_labelmap.end();
// see if we've written out this domain before
@@ -218,6 +216,10 @@
if(unescaped) {
string part(label.c_str() + i -> first, i->second - i->first);
replace_all(part, "\\.", ".");
+ replace_all(part, "\\\\", "\\");
+ if(part.size() > 255)
+ throw MOADNSException("Attempting to express a label of invalid size in xfrLabel");
+
d_record.push_back(part.size());
unsigned int len=d_record.size();
d_record.resize(len + part.size());
--- pdns-recursor-3.1.7/dnswriter.hh
+++ pdns-recursor-3.1.7/dnswriter.hh
@@ -107,4 +107,8 @@
uint16_t d_rollbackmarker; // start of last complete packet, for rollback
Place d_recordplace;
};
+
+typedef vector<pair<std::string::size_type, std::string::size_type> > labelparts_t;
+
+bool labeltokUnescape(labelparts_t& parts, const std::string& label);
#endif
--- pdns-recursor-3.1.7/lwres.cc
+++ pdns-recursor-3.1.7/lwres.cc
@@ -155,7 +155,7 @@
lwr->d_tcbit=mdp.d_header.tc;
lwr->d_rcode=mdp.d_header.rcode;
- if(Utility::strcasecmp(domain.c_str(), mdp.d_qname.c_str())) {
+ if(!pdns_iequals(domain,mdp.d_qname)) {
if(domain.find((char)0)==string::npos) {// embedded nulls are too noisy
L<<Logger::Notice<<"Packet purporting to come from remote server "<<ip.toString()<<" contained wrong answer: '" << domain << "' != '" << mdp.d_qname << "'" << endl;
g_stats.unexpectedCount++;
--- pdns-recursor-3.1.7/misc.hh
+++ pdns-recursor-3.1.7/misc.hh
@@ -318,54 +318,45 @@
{
return tv.tv_sec + tv.tv_usec/1000000.0f;
}
-struct CIStringCompare: public binary_function<string, string, bool>
+
+inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b) __attribute__((pure));
+inline bool pdns_ilexicographical_compare(const std::string& a, const std::string& b)
{
- bool operator()(const string& a, const string& b) const
- {
- const unsigned char *p1 = (const unsigned char *) a.c_str();
- const unsigned char *p2 = (const unsigned char *) b.c_str();
- int result;
-
- if (p1 == p2)
- return 0;
-
- while ((result = dns_tolower (*p1) - dns_tolower (*p2++)) == 0)
- if (*p1++ == '\0')
- break;
-
- return result < 0;
+ string::size_type aLen = a.length(), bLen = b.length(), n;
+ const char *aPtr = a.c_str(), *bPtr = b.c_str();
+ int result;
+
+ for(n = 0 ; n < aLen && n < bLen ; ++n) {
+ if((result = dns_tolower(*aPtr++) - dns_tolower(*bPtr++))) {
+ return result < 0;
+ }
}
+ if(n == aLen && n == bLen) // strings are equal (in length)
+ return 0;
+ if(n == aLen) // first string was shorter
+ return true;
+ return false;
+}
- bool operator()(const string& a, const char* b) const
- {
- const unsigned char *p1 = (const unsigned char *) a.c_str();
- const unsigned char *p2 = (const unsigned char *) b;
- int result;
-
- if (p1 == p2)
- return 0;
-
- while ((result = dns_tolower (*p1) - dns_tolower (*p2++)) == 0)
- if (*p1++ == '\0')
- break;
-
- return result < 0;
+inline bool pdns_iequals(const std::string& a, const std::string& b) __attribute__((pure));
+
+inline bool pdns_iequals(const std::string& a, const std::string& b)
+{
+ string::size_type aLen = a.length(), bLen = b.length(), n;
+ const char *aPtr = a.c_str(), *bPtr = b.c_str();
+
+ for(n = 0 ; n < aLen && n < bLen ; ++n) {
+ if(dns_tolower(*aPtr++) != dns_tolower(*bPtr++))
+ return false;
}
+ return aLen == bLen; // strings are equal (in length)
+}
- bool operator()(const char* a, const string& b) const
+struct CIStringCompare: public binary_function<string, string, bool>
+{
+ bool operator()(const string& a, const string& b) const
{
- const unsigned char *p1 = (const unsigned char *) a;
- const unsigned char *p2 = (const unsigned char *) b.c_str();
- int result;
-
- if (p1 == p2)
- return 0;
-
- while ((result = dns_tolower (*p1) - dns_tolower (*p2++)) == 0)
- if (*p1++ == '\0')
- break;
-
- return result < 0;
+ return pdns_ilexicographical_compare(a, b);
}
};
--- pdns-recursor-3.1.7/pdns_recursor.cc
+++ pdns-recursor-3.1.7/pdns_recursor.cc
@@ -806,43 +806,54 @@
}
}
-void questionExpand(const char* packet, uint16_t len, char* qname, int maxlen, uint16_t& type)
+
+static void appendEscapedLabel(string& ret, const char* begin, unsigned char labellen)
+{
+ unsigned char n = 0;
+ for(n = 0 ; n < labellen; ++n)
+ if(begin[n] == '.' || begin[n] == '\\')
+ break;
+
+ if( n == labellen) {
+ ret.append(begin, labellen);
+ return;
+ }
+ string label(begin, labellen);
+ boost::replace_all(label, "\\", "\\\\");
+ boost::replace_all(label, ".", "\\.");
+ ret.append(label);
+}
+
+string questionExpand(const char* packet, uint16_t len, uint16_t& type)
{
type=0;
- const unsigned char* end=(const unsigned char*)packet+len;
- unsigned char* lbegin=(unsigned char*)packet+12;
- unsigned char* pos=lbegin;
+ string ret;
+ if(len < 12)
+ throw runtime_error("Error parsing question in incoming packet: packet too short");
+
+ const unsigned char* end = (const unsigned char*)packet+len;
+ const unsigned char* pos = (const unsigned char*)packet+12;
unsigned char labellen;
-
- // 3www4ds9a2nl0
- char *dst=qname;
- char* lend=dst + maxlen;
if(!*pos)
- *dst++='.';
-
+ ret.assign(1, '.');
+
while((labellen=*pos++) && pos < end) { // "scan and copy"
- if(dst >= lend)
- throw runtime_error("Label length exceeded destination length");
- for(;labellen;--labellen)
- *dst++ = *pos++;
- *dst++='.';
+ if(pos + labellen > end)
+ throw runtime_error("Error parsing question in incoming packet: label extends beyond packet");
+
+ appendEscapedLabel(ret, (const char*) pos, labellen);
+
+ ret.append(1, '.');
+ pos += labellen;
}
- *dst=0;
- if(pos + labellen + 2 <= end) // is this correct XXX FIXME?
+ if(pos + labellen + 2 <= end)
type=(*pos)*256 + *(pos+1);
-
-
- // cerr<<"Returning: '"<< string(tmp+1, pos) <<"'\n";
+ // cerr << "returning: '"<<ret<<"'"<<endl;
+ return ret;
}
-string questionExpand(const char* packet, uint16_t len, uint16_t& type)
-{
- char tmp[512];
- questionExpand(packet, len, tmp, sizeof(tmp), type);
- return tmp;
-}
void handleNewUDPQuestion(int fd, FDMultiplexer::funcparam_t& var)
{
@@ -874,59 +885,6 @@
}
else {
++g_stats.qcounter;
-#if 0
- uint16_t type;
- char qname[256];
- try {
- questionExpand(data, len, qname, sizeof(qname), type);
- }
- catch(exception &e)
- {
- throw MOADNSException(e.what());
- }
-
- // must all be same length answers right now!
- if((type==QType::A || type==QType::AAAA) && dh->arcount==0 && dh->ancount==0 && dh->nscount ==0 && ntohs(dh->qdcount)==1 ) {
- char *record[10];
- uint16_t rlen[10];
- uint32_t ttd[10];
- int count;
- if((count=RC.getDirect(g_now.tv_sec, qname, QType(type), ttd, record, rlen))) {
- if(len + count*(sizeof(dnsrecordheader) + 2 + rlen[0]) > 512)
- goto slow;
-
- random_shuffle(record, &record[count]);
- dh->qr=1;
- dh->ra=1;
- dh->ancount=ntohs(count);
- for(int n=0; n < count ; ++n) {
- memcpy(data+len, "\xc0\x0c", 2); // answer label pointer
- len+=2;
- struct dnsrecordheader drh;
- drh.d_type=htons(type);
- drh.d_class=htons(1);
- drh.d_ttl=htonl(ttd[n] - g_now.tv_sec);
- drh.d_clen=htons(rlen[n]);
- memcpy(data+len, &drh, sizeof(drh));
- len+=sizeof(drh);
- memcpy(data+len, record[n], rlen[n]);
- len+=rlen[n];
- }
- RDTSC(tsc2);
- g_stats.shunted++;
- sendto(fd, data, len, 0, (struct sockaddr *)(&fromaddr), fromaddr.getSocklen());
-// cerr<<"shunted: " << (tsc2-tsc1) / 3000.0 << endl;
- return;
- }
- }
- else {
- if(type!=QType::A && type!=QType::AAAA)
- g_stats.noShuntWrongType++;
- else
- g_stats.noShuntWrongQuestion++;
- }
- slow:
-#endif
DNSComboWriter* dc = new DNSComboWriter(data, len, g_now);
dc->setSocket(fd);
dc->setRemote(&fromaddr);
@@ -1304,7 +1262,13 @@
pident.remote=fromaddr;
pident.id=dh.id;
pident.fd=fd;
- pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
+ try {
+ pident.domain=questionExpand(data, len, pident.type); // don't copy this from above - we need to do the actual read
+ }
+ catch(...) {
+ return;
+ }
+
string packet;
packet.assign(data, len);
@@ -1322,7 +1286,7 @@
for(MT_t::waiters_t::iterator mthread=MT->d_waiters.begin(); mthread!=MT->d_waiters.end(); ++mthread) {
if(pident.fd==mthread->key.fd && mthread->key.remote==pident.remote && mthread->key.type == pident.type &&
- !Utility::strcasecmp(pident.domain.c_str(), mthread->key.domain.c_str())) {
+ pdns_iequals(pident.domain,mthread->key.domain)) {
mthread->key.nearMisses++;
}
}
--- pdns-recursor-3.1.7/rec_channel_rec.cc
+++ pdns-recursor-3.1.7/rec_channel_rec.cc
@@ -294,6 +294,7 @@
return "bye\n";
}
+
if(cmd=="dump-cache")
return doDumpCache(begin, end);
--- pdns-recursor-3.1.7/recursor_cache.cc
+++ pdns-recursor-3.1.7/recursor_cache.cc
@@ -121,74 +121,13 @@
return ret;
}
-int MemRecursorCache::getDirect(time_t now, const char* qname, const QType& qt, uint32_t ttd[10], char* data[10], uint16_t len[10])
-{
- if(!d_cachecachevalid || Utility::strcasecmp(d_cachedqname.c_str(), qname)) {
-// cerr<<"had cache cache miss for '"<<qname<<"'"<<endl;
- d_cachedqname=qname;
- d_cachecache=d_cache.equal_range(tie(qname));
- d_cachecachevalid=true;
- }
- else
- ;
- // cerr<<"had cache cache hit!"<<endl;
-
- if(d_cachecache.first == d_cachecache.second) {
- g_stats.noShuntNoMatch++;
- return false;
- }
-
- pair<cache_t::iterator, cache_t::iterator> range = d_cachecache;
-
- unsigned int n=0;
- for(;range.first != range.second; ++range.first) {
- if(range.first->d_qtype == QType::CNAME) { // if we see a cname, we need the whole shebang (for now)
- g_stats.noShuntCNAME++;
- return false;
- }
- if(range.first->d_qtype != qt.getCode())
- continue;
- if(range.first->getTTD() < (unsigned int) now) {
- g_stats.noShuntExpired++;
- return false;
- }
-
- if(range.first->d_records.empty() || range.first->d_records.size() > 9 ) {
- g_stats.noShuntSize++;
- return false;
- }
-
- size_t limit=range.first->d_records.size();
- n=0;
- for(; n < limit; ++n) {
- data[n]=(char*)range.first->d_records[n].d_string.c_str();
- len[n]=range.first->d_records[n].d_string.length();
- ttd[n]=range.first->d_records[n].d_ttd;
- }
- if(n<10) {
- data[n]=0;
- typedef cache_t::nth_index<1>::type sequence_t;
- sequence_t& sidx=d_cache.get<1>();
- sequence_t::iterator si=d_cache.project<1>(range.first);
- sidx.relocate(sidx.end(), si); // move it in the LRU list
- // can't yet return, need to figure out if there isn't a CNAME that messes things up
- }
- else
- return false;
- }
- if(!n)
- g_stats.noShuntNoMatch++;
- return n;
-
-}
-
int MemRecursorCache::get(time_t now, const string &qname, const QType& qt, set<DNSResourceRecord>* res)
{
unsigned int ttd=0;
// cerr<<"looking up "<< qname+"|"+qt.getName()<<"\n";
- if(!d_cachecachevalid || Utility::strcasecmp(d_cachedqname.c_str(), qname.c_str())) {
+ if(!d_cachecachevalid || !pdns_iequals(d_cachedqname,qname)) {
// cerr<<"had cache cache miss"<<endl;
d_cachedqname=qname;
d_cachecache=d_cache.equal_range(tie(qname));
--- pdns-recursor-3.1.7/syncres.cc
+++ pdns-recursor-3.1.7/syncres.cc
@@ -62,8 +62,8 @@
int SyncRes::beginResolve(const string &qname, const QType &qtype, uint16_t qclass, vector<DNSResourceRecord>&ret)
{
s_queries++;
- if( (qtype.getCode()==QType::PTR && !Utility::strcasecmp(qname.c_str(), "1.0.0.127.in-addr.arpa.")) ||
- (qtype.getCode()==QType::A && qname.length()==10 && !Utility::strcasecmp(qname.c_str(), "localhost."))) {
+ if( (qtype.getCode()==QType::PTR && pdns_iequals(qname, "1.0.0.127.in-addr.arpa.")) ||
+ (qtype.getCode()==QType::A && qname.length()==10 && pdns_iequals(qname, "localhost."))) {
ret.clear();
DNSResourceRecord rr;
rr.qname=qname;
@@ -79,7 +79,7 @@
}
if(qclass==3 && qtype.getCode()==QType::TXT &&
- (!Utility::strcasecmp(qname.c_str(), "version.bind.") || !Utility::strcasecmp(qname.c_str(), "id.server.") || !Utility::strcasecmp(qname.c_str(), "version.pdns.") )
+ (pdns_iequals(qname, "version.bind.") || pdns_iequals(qname, "id.server.") || pdns_iequals(qname, "version.pdns.") )
) {
ret.clear();
DNSResourceRecord rr;
@@ -87,7 +87,7 @@
rr.qtype=qtype;
rr.qclass=qclass;
rr.ttl=86400;
- if(!Utility::strcasecmp(qname.c_str(),"version.bind.") || !Utility::strcasecmp(qname.c_str(),"version.pdns."))
+ if(pdns_iequals(qname, "version.bind.") || pdns_iequals(qname, "version.pdns."))
rr.content="\""+::arg()["version-string"]+"\"";
else
rr.content="\""+s_serverID+"\"";
@@ -571,10 +571,9 @@
{
bool operator()(const pair<string, QType>& a, const pair<string, QType>& b) const
{
- int cmp=Utility::strcasecmp(a.first.c_str(), b.first.c_str());
- if(cmp < 0)
+ if(pdns_ilexicographical_compare(a.first, b.first))
return true;
- if(cmp > 0)
+ if(pdns_ilexicographical_compare(b.first, a.first))
return false;
return a.second < b.second;
@@ -829,7 +828,7 @@
newtarget=i->content;
}
// for ANY answers we *must* have an authoritive answer
- else if(i->d_place==DNSResourceRecord::ANSWER && !Utility::strcasecmp(i->qname.c_str(),qname.c_str()) &&
+ else if(i->d_place==DNSResourceRecord::ANSWER && pdns_iequals(i->qname,qname) &&
(
i->qtype==qtype || (lwr.d_aabit && (qtype==QType(QType::ANY) || magicAddrMatch(qtype, i->qtype) ) )
)
--- pdns-recursor-3.1.7/syncres.hh
+++ pdns-recursor-3.1.7/syncres.hh
@@ -434,12 +434,11 @@
if( tie(remote, ourSock, type) > tie(b.remote, bSock, b.type))
return false;
- int cmp=Utility::strcasecmp(domain.c_str(), b.domain.c_str());
- if(cmp < 0)
+ if(pdns_ilexicographical_compare(domain,b.domain))
return true;
- if(cmp > 0)
- return false;
+ if(pdns_ilexicographical_compare(b.domain,domain))
+ return false;
return tie(fd, id) < tie(b.fd, b.id);
}
};
@@ -455,8 +454,7 @@
if( tie(a.remote, ourSock, a.type) > tie(b.remote, bSock, b.type))
return false;
- int cmp=Utility::strcasecmp(a.domain.c_str(), b.domain.c_str());
- return cmp < 0;
+ return pdns_ilexicographical_compare(a.domain,b.domain);
}
};
extern MemRecursorCache RC;
--- pdns-recursor-3.1.7/unix_utility.cc
+++ pdns-recursor-3.1.7/unix_utility.cc
@@ -174,13 +174,6 @@
::srandom(seed);
}
-// Compares two string, ignoring the case.
-int Utility::strcasecmp( const char *s1, const char *s2 )
-{
- return ::strcasecmp( s1, s2 );
-}
-
-
// Writes a vector.
int Utility::writev(int socket, const iovec *vector, size_t count )
{
--- pdns-recursor-3.1.7/utility.hh
+++ pdns-recursor-3.1.7/utility.hh
@@ -187,9 +187,6 @@
//! Sets the random seed.
static void srandom( unsigned int seed );
- //! Compares two strings and ignores case.
- static int strcasecmp( const char *s1, const char *s2 );
-
//! Drops the program's privileges.
static void dropPrivs( int uid, int gid );
--- pdns-recursor-3.1.7/win32_utility.cc
+++ pdns-recursor-3.1.7/win32_utility.cc
@@ -379,14 +379,6 @@
srand( seed );
}
-
-// Compares two string, ignoring the case.
-int Utility::strcasecmp( const char *s1, const char *s2 )
-{
- return strcmp( s1, s2 );
-}
-
-
// Sleeps for a number of microseconds.
void Utility::usleep( unsigned long usec )
{
--- pdns-recursor-3.1.7/zoneparser-tng.cc
+++ pdns-recursor-3.1.7/zoneparser-tng.cc
@@ -303,7 +303,7 @@
// cout<<"Next part: '"<<nextpart<<"'"<<endl;
- if(!Utility::strcasecmp(nextpart.c_str(), "IN")) {
+ if(pdns_iequals(nextpart, "IN")) {
// cout<<"Ignoring 'IN'\n";
continue;
}