DNSDistributor *distributor = DNSDistributor::Create(::arg().asNum("distributor-threads", 1)); // the big dispatcher!
int num = (int)(unsigned long)number;
g_distributors[num] = distributor;
- DNSPacket question;
- DNSPacket cached;
+ DNSPacket question(true);
+ DNSPacket cached(false);
AtomicCounter &numreceived=*S.getPointer("udp-queries");
AtomicCounter &numreceiveddo=*S.getPointer("udp-do-queries");
}
// parse packet, set 'id', fill out 'ip'
- MOADNSParser mdp(string(buf, len));
+ MOADNSParser mdp(false, string(buf, len));
if(!g_quiet) {
cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
if(dh->rd || dh->qr)
continue;
- MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
+ MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len);
memcpy(&entry.ip, &pr.d_ip->ip_src, 4);
entry.port = pr.d_udp->uh_sport;
ntohs(pr.d_udp->uh_dport)==53 || ntohs(pr.d_udp->uh_sport)==53) &&
pr.d_len > 12) {
try {
- MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
+ MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len);
if(lastreport.tv_sec == 0) {
lastreport = pr.d_pheader.ts;
bool DNSPacket::s_doEDNSSubnetProcessing;
uint16_t DNSPacket::s_udpTruncationThreshold;
-DNSPacket::DNSPacket()
+DNSPacket::DNSPacket(bool isQuery)
{
d_wrapped=false;
d_compress=true;
d_wantsnsid=false;
d_haveednssubnet = false;
d_dnssecOk=false;
+ d_isQuery = isQuery;
}
const string& DNSPacket::getString()
d_rawpacket=orig.d_rawpacket;
d=orig.d;
+
+ d_isQuery = orig.d_isQuery;
}
void DNSPacket::setRcode(int v)
/** convenience function for creating a reply packet from a question packet. Do not forget to delete it after use! */
DNSPacket *DNSPacket::replyPacket() const
{
- DNSPacket *r=new DNSPacket;
+ DNSPacket *r=new DNSPacket(false);
r->setSocket(d_socket);
r->d_anyLocal=d_anyLocal;
r->setRemote(&d_remote);
bool DNSPacket::getTSIGDetails(TSIGRecordContent* trc, string* keyname, string* message) const
{
- MOADNSParser mdp(d_rawpacket);
+ MOADNSParser mdp(d_isQuery, d_rawpacket);
if(!mdp.getTSIGPos())
return false;
return -1;
}
- MOADNSParser mdp(d_rawpacket);
+ MOADNSParser mdp(d_isQuery, d_rawpacket);
EDNSOpts edo;
// ANY OPTION WHICH *MIGHT* BE SET DOWN BELOW SHOULD BE CLEARED FIRST!
class DNSPacket
{
public:
- DNSPacket();
+ DNSPacket(bool isQuery);
DNSPacket(const DNSPacket &orig);
int noparse(const char *mesg, int len); //!< just suck the data inward
string d_tsigkeyname;
string d_tsigprevious;
bool d_tsigtimersonly;
+ bool d_isQuery;
vector<DNSResourceRecord> d_rrs; // 4
};
memcpy(&packet[pos], &drh, sizeof(drh)); pos+=sizeof(drh);
memcpy(&packet[pos], serialized.c_str(), serialized.size()); pos+=(uint16_t)serialized.size();
- MOADNSParser mdp((char*)&*packet.begin(), (unsigned int)packet.size());
+ MOADNSParser mdp(false, (char*)&*packet.begin(), (unsigned int)packet.size());
shared_ptr<DNSRecordContent> ret= mdp.d_answers.begin()->first.d_content;
ret->header.d_type=ret->d_qtype;
ret->label=mdp.d_answers.begin()->first.d_label;
return zmakermap;
}
-void MOADNSParser::init(const char *packet, unsigned int len)
+void MOADNSParser::init(bool query, const char *packet, unsigned int len)
{
if(len < sizeof(dnsheader))
throw MOADNSException("Packet shorter than minimal header");
d_header.nscount=ntohs(d_header.nscount);
d_header.arcount=ntohs(d_header.arcount);
+ if (query && (d_header.qdcount > 1))
+ throw MOADNSException("Query with QD > 1 ("+lexical_cast<string>(d_header.qdcount)+")");
+
uint16_t contentlen=len-sizeof(dnsheader);
d_content.resize(contentlen);
dr.d_label=label;
dr.d_clen=ah.d_clen;
- dr.d_content=boost::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr, pr, d_header.opcode));
+ if (query && (dr.d_place == DNSRecord::Answer || dr.d_place == DNSRecord::Nameserver || (dr.d_type != QType::OPT && dr.d_type != QType::TSIG && dr.d_type != QType::SIG) || ((dr.d_type == QType::TSIG || dr.d_type == QType::SIG) && dr.d_class != QClass::ANY))) {
+ dr.d_content=boost::shared_ptr<DNSRecordContent>(new UnknownRecordContent(dr, pr));
+ }
+ else {
+ dr.d_content=boost::shared_ptr<DNSRecordContent>(DNSRecordContent::mastermake(dr, pr, d_header.opcode));
+ }
+
d_answers.push_back(make_pair(dr, pr.d_pos));
if(dr.d_type == QType::TSIG && dr.d_class == 0xff)
{
public:
//! Parse from a string
- MOADNSParser(const string& buffer) : d_tsigPos(0)
+ MOADNSParser(bool query, const string& buffer) : d_tsigPos(0)
{
- init(buffer.c_str(), (unsigned int)buffer.size());
+ init(query, buffer.c_str(), (unsigned int)buffer.size());
}
//! Parse from a pointer and length
- MOADNSParser(const char *packet, unsigned int len) : d_tsigPos(0)
+ MOADNSParser(bool query, const char *packet, unsigned int len) : d_tsigPos(0)
{
- init(packet, len);
+ init(query, packet, len);
}
dnsheader d_header;
}
private:
void getDnsrecordheader(struct dnsrecordheader &ah);
- void init(const char *packet, unsigned int len);
+ void init(bool query, const char *packet, unsigned int len);
vector<uint8_t> d_content;
uint16_t d_tsigPos;
};
d.id=i->second.id;
memcpy(buffer,&d,sizeof(d)); // commit spoofed id
- DNSPacket p,q;
+ DNSPacket p(false),q(false);
p.parse(buffer,len);
q.parse(buffer,len);
string reply; // needs to be alive at time of sendmsg!
if(i->second.complete) {
- MOADNSParser mdp(p.getString());
+ MOADNSParser mdp(false, p.getString());
// cerr<<"Got completion, "<<mdp.d_answers.size()<<" answers, rcode: "<<mdp.d_header.rcode<<endl;
for(MOADNSParser::answers_t::const_iterator j=mdp.d_answers.begin(); j!=mdp.d_answers.end(); ++j) {
// cerr<<"comp: "<<(int)j->first.d_place-1<<" "<<j->first.d_label<<" " << DNSRecordContent::NumberToType(j->first.d_type)<<" "<<j->first.d_content->getZoneRepresentation()<<endl;
while(s_socket->recvFromAsync(packet, remote)) {
try {
s_weanswers++;
- MOADNSParser mdp(packet.c_str(), packet.length());
+ MOADNSParser mdp(false, packet.c_str(), packet.length());
if(!mdp.d_header.qr) {
cout<<"Received a question from our reference nameserver!"<<endl;
continue;
sent=true;
dh->id=tmp;
}
- MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
+ MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len);
QuestionIdentifier qi=QuestionIdentifier::create(pr.getSource(), pr.getDest(), mdp);
if(!mdp.d_header.qr) {
while(pr.getUDPPacket()) {
try {
- MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
+ MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len);
if(mdp.d_qtype < 256)
counts[mdp.d_qtype]++;
continue;
}
}
- MOADNSParser mdp((const char*)pr.d_payload, pr.d_len);
+ MOADNSParser mdp(false, (const char*)pr.d_payload, pr.d_len);
if(haveRDFilter && mdp.d_header.rd != rdFilter) {
rdFilterMismatch++;
continue;
q->udpUsec = makeUsec(now - tv);
tv=now;
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
if(!mdp.d_header.tc)
return;
g_truncates++;
q->tcpUsec = makeUsec(now - tv);
q->answerSecond = now.tv_sec;
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
// cout<<"Had correct TCP/IP response, "<<mdp.d_answers.size()<<" answers, aabit="<<mdp.d_header.aa<<endl;
if(mdp.d_header.aa)
g_authAnswers++;
lwr->d_result.clear();
try {
lwr->d_tcbit=0;
- MOADNSParser mdp((const char*)buf.get(), len);
+ MOADNSParser mdp(false, (const char*)buf.get(), len);
lwr->d_aabit=mdp.d_header.aa;
lwr->d_tcbit=mdp.d_header.tc;
lwr->d_rcode=mdp.d_header.rcode;
size=recvfrom(sock,buffer,sizeof(buffer),0,(struct sockaddr *)&from,&fromlen);
if(size < 0)
break;
- DNSPacket p;
+ DNSPacket p(true);
p.setRemote(&from);
if(prefilled) // they gave us a preallocated packet
packet=prefilled;
else
- packet=new DNSPacket; // don't forget to free it!
+ packet=new DNSPacket(true); // don't forget to free it!
packet->setSocket(sock);
packet->setRemote(&remote);
throw runtime_error("Unable to receive notification response from PowerDNS: "+stringerror());
string packet(buffer, len);
- MOADNSParser mdp(packet);
+ MOADNSParser mdp(false, packet);
cerr<<"Received notification response with error: "<<RCode::to_s(mdp.d_header.rcode)<<endl;
cerr<<"For: '"<<mdp.d_qname<<"'"<<endl;
throw runtime_error("reading packet from remote: "+stringerror());
string packet(buffer, res);
- MOADNSParser mdp(packet);
+ MOADNSParser mdp(true, packet);
nif.domain = mdp.d_qname;
nif.origID = mdp.d_header.id;
throw runtime_error("reading packet from remote: "+stringerror());
string packet(buffer, len);
- MOADNSParser mdp(packet);
+ MOADNSParser mdp(false, packet);
// cerr<<"Inside notification response for: "<<mdp.d_qname<<endl;
string reply(creply, len);
delete[] creply;
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
//! used to send information to a newborn mthread
struct DNSComboWriter {
- DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(data, len), d_now(now),
+ DNSComboWriter(const char* data, uint16_t len, const struct timeval& now) : d_mdp(true, data, len), d_now(now),
d_tcp(false), d_socket(-1)
{}
MOADNSParser d_mdp;
throw ResolverException("recvfrom error waiting for answer: "+stringerror());
}
- MOADNSParser mdp((char*)buf, err);
+ MOADNSParser mdp(false, (char*)buf, err);
*id=mdp.d_header.id;
*domain = stripDot(mdp.d_qname);
if((len=recvfrom(sock, buffer, sizeof(buffer), 0,(struct sockaddr*)(&from), &addrlen)) < 0)
throw ResolverException("recvfrom error waiting for answer: "+stringerror());
- MOADNSParser mdp(buffer, len);
+ MOADNSParser mdp(false, buffer, len);
return parseResult(mdp, domain, type, id, res);
}
catch(ResolverException &re) {
throw ResolverException("EOF trying to read axfr chunk from remote TCP client");
timeoutReadn(len);
- MOADNSParser mdp(d_buf.get(), len);
+ MOADNSParser mdp(false, d_buf.get(), len);
int err = parseResult(mdp, "", 0, 0, &res);
if(err)
Utility::closesocket(sock);
try {
- MOADNSParser mdp(buf, recvRes);
+ MOADNSParser mdp(false, buf, recvRes);
L<<Logger::Info<<msgPrefix<<"Forward update message to "<<remote.toStringWithPort()<<", result was RCode "<<mdp.d_header.rcode<<endl;
return mdp.d_header.rcode;
}
// RFC2136 uses the same DNS Header and Message as defined in RFC1035.
// This means we can use the MOADNSParser to parse the incoming packet. The result is that we have some different
// variable names during the use of our MOADNSParser.
- MOADNSParser mdp(p->getString());
+ MOADNSParser mdp(false, p->getString());
if (mdp.d_header.qdcount != 1) {
L<<Logger::Warning<<msgPrefix<<"Zone Count is not 1, sending FormErr"<<endl;
return RCode::FormErr;
n+=numread;
}
- MOADNSParser mdp(string(creply, len));
+ MOADNSParser mdp(false, string(creply, len));
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i!=mdp.d_answers.end(); ++i) {
if(i->first.d_type == QType::SOA)
{
sock.recvFrom(reply, dest);
}
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
catch(...) {
continue;
}
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
if(mdp.d_header.rcode == RCode::ServFail)
continue;
void operator()() const
{
- MOADNSParser mdp((const char*)&*d_packet.begin(), d_packet.size());
+ MOADNSParser mdp(false, (const char*)&*d_packet.begin(), d_packet.size());
typedef map<pair<string, QType>, set<DNSResourceRecord>, TCacheComp > tcache_t;
tcache_t tcache;
void operator()() const
{
- MOADNSParser mdp((const char*)&*d_packet.begin(), d_packet.size());
+ MOADNSParser mdp(false, (const char*)&*d_packet.begin(), d_packet.size());
}
const vector<uint8_t>& d_packet;
std::string d_name;
getQuestion(fd, mesg.get(), pktlen, remote);
S.inc("tcp-queries");
- packet=shared_ptr<DNSPacket>(new DNSPacket);
+ packet=shared_ptr<DNSPacket>(new DNSPacket(true));
packet->setRemote(&remote);
packet->d_tcp=true;
packet->setSocket(fd);
}
shared_ptr<DNSPacket> reply;
- shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new DNSPacket);
+ shared_ptr<DNSPacket> cached= shared_ptr<DNSPacket>(new DNSPacket(false));
if(logDNSQueries) {
string remote;
if(packet->hasEDNSSubnet())
}
uint32_t serial = 0;
- MOADNSParser mdp(q->getString());
+ MOADNSParser mdp(false, q->getString());
for(MOADNSParser::answers_t::const_iterator i=mdp.d_answers.begin(); i != mdp.d_answers.end(); ++i) {
const DNSRecord *rr = &i->first;
if (rr->d_type == QType::SOA && rr->d_place == DNSRecord::Nameserver) {
std::string packet("\xf0\x01\x01\x00\x00\x01\x00\x01\x00\x00\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x03www\x08powerdns\x03""com\x00\x00\x01\x00\x01\x00\x00\x00\x10\x00\x04\x7f\x00\x00\x01\x00\x00\x29\x05\x00\x00\x00\x00\x00\x00\x0c\x00\x03\x00\x08powerdns",89);
OPTRecordContent::report();
- MOADNSParser mdp((char*)&*packet.begin(), (unsigned int)packet.size());
+ MOADNSParser mdp(true, (char*)&*packet.begin(), (unsigned int)packet.size());
- getEDNSOpts(mdp, &eo);
+ BOOST_CHECK_EQUAL(getEDNSOpts(mdp, &eo), true);
// this should contain NSID now
BOOST_CHECK_EQUAL(eo.d_packetsize, 1280);
// it should contain NSID option with value 'powerdns', and nothing else
+ BOOST_CHECK_EQUAL(eo.d_options.size(), 1);
BOOST_CHECK_EQUAL(eo.d_options[0].first, 3); // nsid
BOOST_CHECK_EQUAL(eo.d_options[0].second, "powerdns");
}
vector<pair<uint16_t,string > > opts;
DNSPacketWriter pw(pak, "www.powerdns.com", QType::A);
- DNSPacket q, r, r2;
+ DNSPacket q(true), r(false), r2(false);
q.parse((char*)&pak[0], pak.size());
pak.clear();
string reply;
sock.recvFrom(reply, dest);
- MOADNSParser mdp(reply);
+ MOADNSParser mdp(false, reply);
cout<<"Reply to question for qname='"<<mdp.d_qname<<"', qtype="<<DNSRecordContent::NumberToType(mdp.d_qtype)<<endl;
cout<<"Rcode: "<<mdp.d_header.rcode<<", RD: "<<mdp.d_header.rd<<", QR: "<<mdp.d_header.qr;
cout<<", TC: "<<mdp.d_header.tc<<", AA: "<<mdp.d_header.aa<<", opcode: "<<mdp.d_header.opcode<<endl;
makePtr(rr, &ptr);
// verify that there's a zone for the PTR
- DNSPacket fakePacket;
+ DNSPacket fakePacket(false);
SOAData sd;
fakePacket.qtype = QType::PTR;
if (!B.getAuth(&fakePacket, &sd, ptr.qname, 0))
// now the PTRs
BOOST_FOREACH(const DNSResourceRecord& rr, new_ptrs) {
- DNSPacket fakePacket;
+ DNSPacket fakePacket(false);
SOAData sd;
sd.db = (DNSBackend *)-1;
fakePacket.qtype = QType::PTR;