struct NotificationInFlight
{
ComboAddress source;
- time_t sentAt;
+ time_t resentTime;
string domain;
+ uint16_t origID, resentID;
+ int origSocket;
};
+map<uint16_t, NotificationInFlight> g_nifs;
+
void handleOutsideUDPPacket(int fd, boost::any&)
try
{
char buffer[1500];
struct NotificationInFlight nif;
+ nif.origSocket = fd;
socklen_t socklen=sizeof(nif.source);
string packet(buffer, res);
MOADNSParser mdp(packet);
+ nif.domain = mdp.d_qname;
+ nif.origID = mdp.d_header.id;
- cerr<<"Packet for: "<<mdp.d_qname<<endl;
+ cerr<<"Packet for: "<< nif.domain << endl;
if(mdp.d_header.opcode != Opcode::Notify || mdp.d_qtype != QType::SOA) {
cerr<<"Opcode: "<<mdp.d_header.opcode<<", != notify\n";
vector<uint8_t> outpacket;
DNSPacketWriter pw(outpacket, mdp.d_qname, mdp.d_qtype, 1, Opcode::Notify);
- pw.getHeader()->id = random();
+
+ static uint16_t s_idpool;
+ pw.getHeader()->id = nif.resentID = s_idpool++;
+
+ if(send(g_pdnssocket, &outpacket[0], outpacket.size(), 0) < 0) {
+ throw runtime_error("Unable to send notify to PowerDNS: "+stringerror());
+ }
+ nif.resentTime=time(0);
+ g_nifs[nif.resentID] = nif;
+
+}
+catch(exception &e)
+{
+ cerr<<"Error parsing incoming packet: "<<e.what()<<endl;
+}
+
+
+void handleInsideUDPPacket(int fd, boost::any&)
+try
+{
+ char buffer[1500];
+ struct NotificationInFlight nif;
+
+ socklen_t socklen=sizeof(nif.source);
+
+ int res=recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&nif.source, &socklen);
+ if(!res)
+ return;
+
+ if(res < 0)
+ throw runtime_error("reading packet from remote: "+stringerror());
+
+ string packet(buffer, res);
+ MOADNSParser mdp(packet);
+
+ cerr<<"Inside packet for: "<<mdp.d_qname<<endl;
+
+ if(!g_nifs.count(mdp.d_header.id)) {
+ cerr<<"Response from inner PowerDNS with unknown ID "<<mdp.d_header.id<<endl;
+ return;
+ }
+
+ nif=g_nifs[mdp.d_header.id];
+
+ vector<uint8_t> outpacket;
+ DNSPacketWriter pw(outpacket, mdp.d_qname, mdp.d_qtype, 1, Opcode::Notify);
+
+ static uint16_t s_idpool;
+ pw.getHeader()->id = nif.resentID = s_idpool++;
if(send(g_pdnssocket, &outpacket[0], outpacket.size(), 0) < 0) {
throw runtime_error("Unable to send notify to PowerDNS: "+stringerror());
cerr<<"Error parsing incoming packet: "<<e.what()<<endl;
}
+
+
int main(int argc, char** argv)
try
{
if(::bind(sock,(sockaddr*) &local, local.getSocklen()) < 0)
throw runtime_error("Binding socket for incoming packets: "+stringerror());
- // add to fdmultiplexer for each socket
-
- g_fdm.addReadFD(sock, handleOutsideUDPPacket);
+ g_fdm.addReadFD(sock, handleOutsideUDPPacket); // add to fdmultiplexer for each socket
}
+ // create socket that talks to inner PowerDNS
+
g_pdnssocket=socket(AF_INET, SOCK_DGRAM, 0);
if(g_pdnssocket < 0)
throw runtime_error("Creating socket for packets to PowerDNS: "+stringerror());
if(connect(g_pdnssocket, (struct sockaddr*) &pdns, pdns.getSocklen()) < 0)
throw runtime_error("Failed to connect PowerDNS socket to address "+pdns.toString()+": "+stringerror());
+ g_fdm.addReadFD(g_pdnssocket, handleInsideUDPPacket);
+
if(g_vm.count("chroot")) {
if(chroot(g_vm["chroot"].as<string>().c_str()) < 0)
throw runtime_error("while chrooting to "+g_vm["chroot"].as<string>());