Changeset 1082

Show
Ignore:
Timestamp:
08/13/07 16:40:02 (3 years ago)
Author:
ahu
Message:

almost there

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/pdns/pdns/nproxy.cc

    r1077 r1082  
    1010#include <boost/multi_index/ordered_index.hpp> 
    1111#include <boost/multi_index/key_extractors.hpp> 
     12#include <boost/algorithm/string.hpp> 
     13#include <sys/types.h> 
     14#include <sys/stat.h> 
     15#include <fcntl.h> 
    1216 
    1317#include "mplexer.hh" 
     
    2226SelectFDMultiplexer g_fdm; 
    2327int g_pdnssocket; 
     28bool g_verbose; 
    2429 
    2530struct NotificationInFlight 
     
    3237}; 
    3338 
    34 map<uint16_t, NotificationInFlight> g_nifs; 
     39typedef map<uint16_t, NotificationInFlight> nifs_t; 
     40nifs_t g_nifs; 
    3541 
    3642void handleOutsideUDPPacket(int fd, boost::any&) 
     
    5561  nif.origID = mdp.d_header.id; 
    5662 
    57   cerr<<"Packet for: "<< nif.domain << endl; 
     63  cerr<<"External notification received for: "<< nif.domain << endl; 
    5864 
    5965  if(mdp.d_header.opcode != Opcode::Notify || mdp.d_qtype != QType::SOA) { 
     
    8995  socklen_t socklen=sizeof(nif.source); 
    9096 
    91   int res=recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&nif.source, &socklen); 
    92   if(!res) 
     97  int len=recvfrom(fd, buffer, sizeof(buffer), 0, (struct sockaddr*)&nif.source, &socklen); 
     98  if(!len) 
    9399    return; 
    94100 
    95   if(res < 0)  
     101  if(len < 0)  
    96102    throw runtime_error("reading packet from remote: "+stringerror()); 
    97103     
    98   string packet(buffer, res); 
     104  string packet(buffer, len); 
    99105  MOADNSParser mdp(packet); 
    100106 
    101   cerr<<"Inside packet for: "<<mdp.d_qname<<endl; 
     107  cerr<<"Inside notification response for: "<<mdp.d_qname<<endl; 
    102108 
    103109  if(!g_nifs.count(mdp.d_header.id)) { 
     
    108114  nif=g_nifs[mdp.d_header.id]; 
    109115 
    110   vector<uint8_t> outpacket; 
    111   DNSPacketWriter pw(outpacket, mdp.d_qname, mdp.d_qtype, 1, Opcode::Notify); 
    112  
    113   static uint16_t s_idpool; 
    114   pw.getHeader()->id = nif.resentID = s_idpool++; 
    115    
    116   if(send(g_pdnssocket, &outpacket[0], outpacket.size(), 0) < 0) { 
    117     throw runtime_error("Unable to send notify to PowerDNS: "+stringerror()); 
    118   } 
     116  if(!iequals(nif.domain,mdp.d_qname)) { 
     117    cerr<<"Response from inner PowerDNS for different domain '"<<mdp.d_qname<<"' than original notification '"<<nif.domain<<"'"<<endl; 
     118  } else { 
     119    struct dnsheader dh; 
     120    memcpy(&dh, buffer, sizeof(dh)); 
     121    dh.id = nif.origID; 
     122     
     123    if(sendto(nif.origSocket, buffer, len, 0, (sockaddr*) &nif.source, nif.source.getSocklen()) < 0) { 
     124      throw runtime_error("Unable to send notify to PowerDNS: "+stringerror()); 
     125    } 
     126  } 
     127  g_nifs.erase(mdp.d_header.id); 
    119128 
    120129} 
     
    124133} 
    125134 
    126  
     135void expireOldNotifications() 
     136{ 
     137  time_t limit = time(0) - 10; 
     138  for(nifs_t::iterator iter = g_nifs.begin(); iter != g_nifs.end(); ) { 
     139    if(iter->second.resentTime < limit) { 
     140      cerr<<"Removing notification proxy entry for '"<<iter->second.domain<<"', expired"<<endl; 
     141      g_nifs.erase(iter++); 
     142    } 
     143    else 
     144      ++iter; 
     145  } 
     146} 
     147 
     148void daemonize(); 
    127149 
    128150int main(int argc, char** argv) 
     
    132154  desc.add_options() 
    133155    ("help,h", "produce help message") 
    134     ("powerdns-ip", po::value<string>(), "IP address of PowerDNS server") 
    135     ("local-address", po::value<vector<string> >(), "IP addresses to listen on"); 
     156    ("powerdns-address", po::value<string>(), "IP address of PowerDNS server") 
     157    ("origin-address", po::value<string>()->default_value("::"), "Source address for notifications to PowerDNS") 
     158    ("listen-address", po::value<vector<string> >(), "IP addresses to listen on") 
     159    ("daemon,d", po::value<bool>()->default_value(true), "operate in the background") 
     160    ("verbose,v", "be verbose"); 
    136161 
    137162  po::store(po::command_line_parser(argc, argv).options(desc).run(), g_vm); 
     
    143168  } 
    144169 
    145   if(!g_vm.count("powerdns-ip")) { 
    146     cerr<<"Mandatory setting 'powerdns-ip' unset:\n"<<desc<<endl; 
     170  if(!g_vm.count("powerdns-address")) { 
     171    cerr<<"Mandatory setting 'powerdns-address' unset:\n"<<desc<<endl; 
    147172    return EXIT_FAILURE; 
    148173  } 
     174 
     175  if(!g_vm.count("verbose")) { 
     176    g_verbose=true; 
     177  } 
    149178   
    150179  vector<string> addresses; 
    151   if(g_vm.count("local-address")) 
    152     addresses=g_vm["local-address"].as<vector<string> >(); 
     180  if(g_vm.count("listen-address")) 
     181    addresses=g_vm["listen-address"].as<vector<string> >(); 
    153182  else 
    154183    addresses.push_back("::"); 
     
    164193 
    165194    if(::bind(sock,(sockaddr*) &local, local.getSocklen()) < 0) 
    166       throw runtime_error("Binding socket for incoming packets: "+stringerror()); 
     195      throw runtime_error("Binding socket for incoming packets to '"+ local.toStringWithPort()+"': "+stringerror()); 
    167196 
    168197    g_fdm.addReadFD(sock, handleOutsideUDPPacket); // add to fdmultiplexer for each socket 
     
    175204    throw runtime_error("Creating socket for packets to PowerDNS: "+stringerror()); 
    176205 
    177   ComboAddress pdns(g_vm["powerdns-ip"].as<string>(), 53); 
     206  ComboAddress originAddress(g_vm["origin-address"].as<string>(), 0); 
     207  if(::bind(g_pdnssocket,(sockaddr*) &originAddress, originAddress.getSocklen()) < 0) 
     208      throw runtime_error("Binding local address of inward socket to '"+ originAddress.toStringWithPort()+"': "+stringerror()); 
     209   
     210 
     211  ComboAddress pdns(g_vm["powerdns-address"].as<string>(), 53); 
    178212  if(connect(g_pdnssocket, (struct sockaddr*) &pdns, pdns.getSocklen()) < 0)  
    179213    throw runtime_error("Failed to connect PowerDNS socket to address "+pdns.toString()+": "+stringerror()); 
     
    185219      throw runtime_error("while chrooting to "+g_vm["chroot"].as<string>()); 
    186220  } 
     221 
     222  if(g_vm["daemon"].as<bool>()) { 
     223    daemonize(); 
     224  } 
     225 
    187226 
    188227  // start loop 
     
    192231    g_fdm.run(&now); 
    193232    // check for notifications that have been outstanding for more than 10 seconds 
    194     cerr<<".\n"; 
    195   } 
    196  
    197    
    198  
     233    expireOldNotifications(); 
     234  } 
    199235} 
    200236catch(exception& e) 
    201237{ 
    202238  cerr<<"Fatal: "<<e.what()<<endl; 
     239} 
     240catch(AhuException& e) 
     241{ 
     242  cerr<<"Fatal: "<<e.reason<<endl; 
    203243} 
    204244 
     
    247287  return false; 
    248288} 
     289 
     290void daemonize(void) 
     291{ 
     292  if(fork()) 
     293    exit(0); // bye bye 
     294   
     295  setsid();  
     296 
     297  int i=open("/dev/null",O_RDWR); /* open stdin */ 
     298  if(i < 0)  
     299    cerr<<"Unable to open /dev/null: "<<stringerror()<<endl; 
     300  else { 
     301    dup2(i,0); /* stdin */ 
     302    dup2(i,1); /* stderr */ 
     303    dup2(i,2); /* stderr */ 
     304    close(i); 
     305  } 
     306}