try {
Resolver resolver;
uint32_t theirserial;
- int res=resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
- if(res<=0) {
- L<<Logger::Error<<"Unable to determine SOA serial for "<<p->qdomain<<" at potential supermaster "<<p->getRemote()<<endl;
- return RCode::ServFail;
- }
+ resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
resolver.resolve(p->getRemote(),p->qdomain.c_str(), QType::NS);
nsset=resolver.result();
}
catch(ResolverException &re) {
- L<<Logger::Error<<"Error resolving SOA or NS for '"<<p->qdomain<<"' at "<<p->getRemote()<<endl;
+ L<<Logger::Error<<"Error resolving SOA or NS at: "<< p->getRemote() <<": "<<re.reason<<endl;
return RCode::ServFail;
}
/* this is an instant DoS, just spoof notifications from the address of the master and we block */
Resolver resolver;
- int res=resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
- if(res<=0) {
- L<<Logger::Error<<"Unable to determine SOA serial for "<<p->qdomain<<" at "<<p->getRemote()<<endl;
+ try {
+ resolver.getSoaSerial(p->getRemote(),p->qdomain, &theirserial);
+ }
+ catch(ResolverException& re) {
+ L<<Logger::Error<<re.reason<<endl;
return RCode::ServFail;
}
int Resolver::notify(int sock, const string &domain, const string &ip, uint16_t id)
{
vector<uint8_t> packet;
- DNSPacketWriter pw(packet, domain, QType::SOA, Opcode::Notify);
- pw.getHeader()->id = id;
+ DNSPacketWriter pw(packet, domain, QType::SOA, 1, Opcode::Notify);
+ pw.getHeader()->id = d_randomid = id;
ComboAddress dest(ip, 53);
{
vector<uint8_t> packet;
DNSPacketWriter pw(packet, domain, type);
+ pw.getHeader()->id = d_randomid = random();
d_domain=domain;
d_type=type;
int Resolver::resolve(const string &ip, const char *domain, int type)
{
makeUDPSocket();
- sendResolve(ip,domain,type);
+ sendResolve(ip, domain, type);
try {
struct sockaddr_in from;
return receiveResolve((sockaddr*)&from, sizeof(from));
vector<uint8_t> packet;
DNSPacketWriter pw(packet, domain, QType::AXFR);
+ pw.getHeader()->id = d_randomid = random();
uint16_t replen=htons(packet.size());
Utility::iovec iov[2];
return 1;
}
-
Resolver::res_t Resolver::result()
{
shared_ptr<MOADNSParser> mdp;
catch(...) {
throw ResolverException("resolver: unable to parse packet of "+itoa(d_len)+" bytes");
}
+ if(mdp->d_header.id != d_randomid) {
+ throw ResolverException("Remote nameserver replied with wrong id");
+ }
if(mdp->d_header.rcode)
if(d_inaxfr)
throw ResolverException("Remote nameserver unable/unwilling to AXFR with us: RCODE="+itoa(mdp->d_header.rcode));
rr.content=unquotify(rr.content);
if(rr.qtype.getCode() == QType::MX) {
-
vector<string> parts;
stringtok(parts, rr.content);
rr.priority = atoi(parts[0].c_str());
return ret;
}
-void Resolver::sendSoaSerialRequest(const string &ip, const string &domain)
-{
- sendResolve(ip,domain.c_str(),QType::SOA);
-}
-
-int Resolver::getSoaSerialAnswer(string &master, string &zone, uint32_t* serial)
+void Resolver::getSoaSerial(const string &ip, const string &domain, uint32_t *serial)
{
- struct sockaddr_in fromaddr;
- Utility::socklen_t addrlen=sizeof(fromaddr);
-
- receiveResolve((struct sockaddr*)&fromaddr, addrlen);
+ resolve(ip, domain.c_str(), QType::SOA);
res_t res=result();
if(res.empty())
- return 0;
-
- vector<string>parts;
- stringtok(parts,res[0].content);
- if(parts.size()<3)
- return 0;
-
- *serial=strtoul(parts[2].c_str(), NULL, 10);
- master=""; // fix this!!
- zone=res[0].qname;
-
- return 1;
-}
+ throw ResolverException("Query to '" + ip + "' for SOA of '" + domain + "' produced no answers");
+ if(res[0].qtype.getCode() != QType::SOA)
+ throw ResolverException("Query to '" + ip + "' for SOA of '" + domain + "' produced a "+res[0].qtype.getName()+" record");
-int Resolver::getSoaSerial(const string &ip, const string &domain, uint32_t *serial)
-{
- resolve(ip,domain.c_str(),QType::SOA);
- res_t res=result();
- if(res.empty())
- return 0;
-
vector<string>parts;
- stringtok(parts,res[0].content);
+ stringtok(parts, res[0].content);
if(parts.size()<3)
- return 0;
+ throw ResolverException("Query to '" + ip + "' for SOA of '" + domain + "' produced an unparseable response");
*serial=(uint32_t)atol(parts[2].c_str());
- return 1;
}
int receiveResolve(struct sockaddr* fromaddr, Utility::socklen_t addrlen);
char* sendReceive(const string &ip, uint16_t remotePort, const char *packet, int length, unsigned int *replylen);
- int getSoaSerial(const string &, const string &, uint32_t *);
- void sendSoaSerialRequest(const string &ip, const string &domain);
- int getSoaSerialAnswer(string &master, string &zone, uint32_t* serial);
+ void getSoaSerial(const string &, const string &, uint32_t *);
int axfrChunk(Resolver::res_t &res);
vector<DNSResourceRecord> result();
int d_type;
int d_timeout;
uint32_t d_ip;
+ uint16_t d_randomid;
bool d_inaxfr;
ComboAddress d_toaddr;
};