Changeset 678

Show
Ignore:
Timestamp:
04/11/06 18:09:50 (7 years ago)
Author:
ahu
Message:

add counts for broken packets
add switch to prevent logging rather common errors
removed duplicate answer parsing (!!)
improved TCP timeout code, previously we could time out a running TCP query, which was wrong
improve error message consistency slightly

Location:
trunk/pdns/pdns
Files:
4 modified

Legend:

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

    r670 r678  
    236236  } 
    237237  catch(out_of_range &re) { 
    238     throw MOADNSException("Packet parsing error, out of bounds: "+string(re.what())); 
     238    throw MOADNSException("Error parsing packet of "+lexical_cast<string>(len)+" bytes, out of bounds: "+string(re.what())); 
    239239  } 
    240240} 
  • trunk/pdns/pdns/pdns_recursor.cc

    r673 r678  
    269269} 
    270270 
     271map<uint32_t, uint32_t> g_tcpClientCounts; 
     272 
     273struct TCPConnection 
     274{ 
     275  int fd; 
     276  enum {BYTE0, BYTE1, GETQUESTION, DONE} state; 
     277  int qlen; 
     278  int bytesread; 
     279  struct sockaddr_in remote; 
     280  char data[65535]; 
     281  time_t startTime; 
     282 
     283  void closeAndCleanup() 
     284  { 
     285    close(fd); 
     286    if(!g_tcpClientCounts[remote.sin_addr.s_addr]--)  
     287      g_tcpClientCounts.erase(remote.sin_addr.s_addr); 
     288  } 
     289}; 
     290 
     291vector<TCPConnection> g_tcpconnections; // all *running* TCP/IP questions (from clients) 
     292 
    271293void startDoResolve(void *p) 
    272294{ 
     
    352374 
    353375      int ret=writev(dc->d_socket, iov, 2); 
    354  
    355       if(ret <= 0 )  
    356         L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< (ret ? strerror(errno) : "EOF") <<endl; 
     376      bool hadError=true; 
     377 
     378      if(ret == 0)  
     379        L<<Logger::Error<<"EOF writing TCP answer to "<<dc->getRemote()<<endl; 
     380      else if(ret < 0 )   
     381        L<<Logger::Error<<"Error writing TCP answer to "<<dc->getRemote()<<": "<< strerror(errno) <<endl; 
    357382      else if((unsigned int)ret != 2 + packet.size()) 
    358383        L<<Logger::Error<<"Oops, partial answer sent to "<<dc->getRemote()<<" for "<<dc->d_mdp.d_qname<<" (size="<< (2 + packet.size()) <<", sent "<<ret<<")"<<endl; 
     384      else 
     385        hadError=false; 
     386 
     387      for(vector<TCPConnection>::iterator i=g_tcpconnections.begin();i!=g_tcpconnections.end();++i) { 
     388        if(i->fd == dc->d_socket) { 
     389          if(hadError) { 
     390            i->closeAndCleanup(); 
     391            g_tcpconnections.erase(i); 
     392          } 
     393          else { 
     394            i->state=TCPConnection::BYTE0; 
     395            i->startTime=time(0); // needs to be current, TCP is slow anyhow 
     396          } 
     397          break; 
     398        } 
     399      } 
    359400    } 
    360401 
     
    618659} 
    619660 
    620 map<uint32_t, uint32_t> g_tcpClientCounts; 
    621 struct TCPConnection 
    622 { 
    623   int fd; 
    624   enum {BYTE0, BYTE1, GETQUESTION} state; 
    625   int qlen; 
    626   int bytesread; 
    627   struct sockaddr_in remote; 
    628   char data[65535]; 
    629   time_t startTime; 
    630  
    631   void closeAndCleanup() 
    632   { 
    633     close(fd); 
    634     if(!g_tcpClientCounts[remote.sin_addr.s_addr]--)  
    635       g_tcpClientCounts.erase(remote.sin_addr.s_addr); 
    636   } 
    637 }; 
     661 
    638662 
    639663#if 0 
     
    702726    ::arg().set("trace","if we should output heaps of logging")="off"; 
    703727    ::arg().set("daemon","Operate as a daemon")="yes"; 
     728    ::arg().set("log-common-errors","If we should log rather common errors")="yes"; 
    704729    ::arg().set("chroot","switch to chroot jail")=""; 
    705730    ::arg().set("setgid","If set, change group id to this gid for more security")=""; 
     
    755780 
    756781    L<<Logger::Warning<<"Operating in "<<(sizeof(unsigned long)*8) <<" bits mode"<<endl; 
    757   L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. " 
    758     "This is free software, and you are welcome to redistribute it " 
    759     "according to the terms of the GPL version 2."<<endl; 
    760  
    761  
    762   g_quiet=::arg().mustDo("quiet"); 
    763   if(::arg().mustDo("trace")) { 
     782    L<<Logger::Warning<<"PowerDNS comes with ABSOLUTELY NO WARRANTY. " 
     783      "This is free software, and you are welcome to redistribute it " 
     784      "according to the terms of the GPL version 2."<<endl; 
     785     
     786     
     787    g_quiet=::arg().mustDo("quiet"); 
     788    if(::arg().mustDo("trace")) { 
    764789      SyncRes::setLog(true); 
    765790      ::arg().set("quiet")="no"; 
    766791      g_quiet=false; 
    767   } 
     792    } 
     793 
     794    bool logCommonErrors=::arg().mustDo("log-common-errors"); 
    768795 
    769796    makeUDPServerSockets(); 
     
    815842    Utility::dropPrivs(newuid, newgid); 
    816843 
    817     vector<TCPConnection> tcpconnections; 
     844 
    818845    counter=0; 
    819846    struct timeval now; 
     
    846873      int fdmax=max(d_clientsock, s_rcc.d_fd); 
    847874 
    848       if(!tcpconnections.empty()) 
     875      if(!g_tcpconnections.empty()) 
    849876        gettimeofday(&now, 0); 
    850877 
    851878      vector<TCPConnection> sweeped; 
    852879 
    853       for(vector<TCPConnection>::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) { 
    854         if(now.tv_sec < i->startTime + tcpTimeout) { 
    855           FD_SET(i->fd, &readfds); 
    856           fdmax=max(fdmax,i->fd); 
     880      for(vector<TCPConnection>::iterator i=g_tcpconnections.begin();i!=g_tcpconnections.end();++i) { 
     881        if(i->state==TCPConnection::DONE || now.tv_sec < i->startTime + tcpTimeout) {  // don't timeout when we are working on the question! 
    857882          sweeped.push_back(*i); 
     883          if(i->state!=TCPConnection::DONE) { // we don't listen for data when we are processing the question 
     884            FD_SET(i->fd, &readfds); 
     885            fdmax=max(fdmax,i->fd); 
     886          } 
    858887        } 
    859888        else { 
    860           L<<Logger::Error<<"TCP timeout from client "<<inet_ntoa(i->remote.sin_addr)<<endl; 
     889          if(logCommonErrors) 
     890            L<<Logger::Error<<"TCP timeout from client "<<inet_ntoa(i->remote.sin_addr)<<endl; 
    861891          i->closeAndCleanup(); 
    862892        } 
    863893      } 
    864       sweeped.swap(tcpconnections); 
     894      sweeped.swap(g_tcpconnections); 
    865895 
    866896      for(vector<int>::const_iterator i=d_udpserversocks.begin(); i!=d_udpserversocks.end(); ++i) { 
     
    868898        fdmax=max(fdmax,*i); 
    869899      } 
    870       if(tcpconnections.size() < maxTcpClients)  
     900      if(g_tcpconnections.size() < maxTcpClients)  
    871901        for(tcpserversocks_t::const_iterator i=s_tcpserversocks.begin(); i!=s_tcpserversocks.end(); ++i) { 
    872902          FD_SET(*i, &readfds ); 
     
    904934      } 
    905935 
    906       if(FD_ISSET(d_clientsock,&readfds)) { // do we have a UDP question response? 
     936      if(FD_ISSET(d_clientsock,&readfds)) { // do we have a UDP question response from a server ("we are the client", hence d_clientsock) 
    907937        while((d_len=recvfrom(d_clientsock, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) { 
    908         try { 
    909             DNSComboWriter dc(data, d_len, now); 
    910             dc.setRemote((struct sockaddr *)&fromaddr, addrlen); 
    911  
    912             if(dc.d_mdp.d_header.qr) { 
     938          dnsheader dh; 
     939          if(d_len >= sizeof(dnsheader)) { 
     940            memcpy(&dh, data, sizeof(dh)); 
     941             
     942            if(dh.qr) { 
    913943              pident.remote=fromaddr; 
    914               pident.id=dc.d_mdp.d_header.id; 
     944              pident.id=dh.id; 
    915945              string packet; 
    916946              packet.assign(data, d_len); 
     
    918948            } 
    919949            else  
    920               L<<Logger::Warning<<"Ignoring question on outgoing socket from "<<dc.getRemote()<<endl; 
    921           } 
    922           catch(MOADNSException& mde) { 
    923             L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen) <<": "<<mde.what()<<endl; 
     950              L<<Logger::Warning<<"Ignoring question on outgoing socket from "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen)  <<endl; 
     951          } 
     952          else { 
     953            g_stats.serverParseError++;  
     954            if(logCommonErrors) 
     955              L<<Logger::Error<<"Unable to parse packet from remote UDP server "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen) <<": packet too small"<<endl; 
    924956          } 
    925957        } 
     
    929961        if(FD_ISSET(*i,&readfds)) { // do we have a new question on udp? 
    930962          while((d_len=recvfrom(*i, data, sizeof(data), 0, (sockaddr *)&fromaddr, &addrlen)) >= 0) { 
    931             g_stats.queryrate.pulse(now); 
     963            //      g_stats.queryrate.pulse(now);  // (broken) 
    932964            if(g_allowFrom && !g_allowFrom->match(&fromaddr)) { 
    933965              g_stats.unauthorizedUDP++; 
     
    940972              dc->setRemote((struct sockaddr *)&fromaddr, addrlen); 
    941973 
    942               if(dc->d_mdp.d_header.qr) 
    943                 L<<Logger::Error<<"Ignoring answer on server socket!"<<endl; 
     974              if(dc->d_mdp.d_header.qr) { 
     975                if(logCommonErrors) 
     976                  L<<Logger::Error<<"Ignoring answer from "<<dc->getRemote()<<" on server socket!"<<endl; 
     977              } 
    944978              else { 
    945979                ++g_stats.qcounter; 
     
    950984            } 
    951985            catch(MOADNSException& mde) { 
     986              g_stats.clientParseError++;  
    952987              L<<Logger::Error<<"Unable to parse packet from remote UDP client "<< sockAddrToString((struct sockaddr_in*) &fromaddr, addrlen) <<": "<<mde.what()<<endl; 
    953988            } 
     
    957992 
    958993      for(tcpserversocks_t::const_iterator i=s_tcpserversocks.begin(); i!=s_tcpserversocks.end(); ++i) {  
    959         if(FD_ISSET(*i ,&readfds)) { // do we have a new TCP connection? 
     994        if(FD_ISSET(*i ,&readfds)) { // do we have a new TCP connection from a client? 
    960995          struct sockaddr_in addr; 
    961996          socklen_t addrlen=sizeof(addr); 
     
    9801015            tc.remote=addr; 
    9811016            tc.startTime=now.tv_sec; 
    982             tcpconnections.push_back(tc); 
     1017            g_tcpconnections.push_back(tc); 
    9831018          } 
    9841019        } 
     
    10451080       
    10461081      // very braindead TCP incoming question parser 
    1047       for(vector<TCPConnection>::iterator i=tcpconnections.begin();i!=tcpconnections.end();++i) { 
     1082      for(vector<TCPConnection>::iterator i=g_tcpconnections.begin();i!=g_tcpconnections.end();++i) { 
    10481083        if(FD_ISSET(i->fd, &readfds)) { 
    10491084          if(i->state==TCPConnection::BYTE0) { 
     
    10581093            if(!bytes || bytes < 0) { 
    10591094              i->closeAndCleanup(); 
    1060               tcpconnections.erase(i); 
     1095              g_tcpconnections.erase(i); 
    10611096              break; 
    10621097            } 
     
    10701105            } 
    10711106            if(!bytes || bytes < 0) { 
    1072               L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected after first byte"<<endl; 
     1107              if(logCommonErrors) 
     1108                L<<Logger::Error<<"TCP client "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected after first byte"<<endl; 
    10731109              i->closeAndCleanup(); 
    1074               tcpconnections.erase(i); 
     1110              g_tcpconnections.erase(i); 
    10751111              break; 
    10761112            } 
    1077              
    10781113          } 
    10791114          else if(i->state==TCPConnection::GETQUESTION) { 
    10801115            int bytes=read(i->fd,i->data + i->bytesread,i->qlen - i->bytesread); 
    10811116            if(!bytes || bytes < 0) { 
    1082               L<<Logger::Error<<"TCP Remote "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected while reading question body"<<endl; 
     1117              L<<Logger::Error<<"TCP client "<<sockAddrToString(&i->remote,sizeof(i->remote))<<" disconnected while reading question body"<<endl; 
    10831118              i->closeAndCleanup(); 
    1084               tcpconnections.erase(i); 
     1119              g_tcpconnections.erase(i); 
    10851120              break; 
    10861121            } 
    10871122            i->bytesread+=bytes; 
    10881123            if(i->bytesread==i->qlen) { 
    1089               i->state=TCPConnection::BYTE0; 
     1124              i->state=TCPConnection::DONE; // this makes us immune from timeouts, from now on *we* are responsible 
    10901125              DNSComboWriter* dc=0; 
    10911126              try { 
     
    10931128              } 
    10941129              catch(MOADNSException &mde) { 
    1095                 L<<Logger::Error<<"Unable to parse packet from remote TCP client "<<sockAddrToString(&i->remote,sizeof(i->remote))<<endl; 
     1130                g_stats.clientParseError++;  
     1131                L<<Logger::Error<<"Unable to parse packet from TCP client "<<sockAddrToString(&i->remote,sizeof(i->remote))<<endl; 
    10961132                i->closeAndCleanup(); 
    1097                 tcpconnections.erase(i); 
     1133                g_tcpconnections.erase(i); 
    10981134                break; 
    10991135              } 
     
    11081144                ++g_stats.tcpqcounter; 
    11091145                MT->makeThread(startDoResolve, dc); 
     1146                break; 
    11101147              } 
    11111148            } 
  • trunk/pdns/pdns/rec_channel_rec.cc

    r669 r678  
    144144  addGetStat("tcp-client-overflow", &g_stats.tcpClientOverflow); 
    145145 
     146  addGetStat("client-parse-errors", &g_stats.clientParseError); 
     147  addGetStat("server-parse-errors", &g_stats.serverParseError); 
     148 
    146149  addGetStat("answers0-1", &g_stats.answers0_1); 
    147150  addGetStat("answers1-10", &g_stats.answers1_10); 
  • trunk/pdns/pdns/syncres.hh

    r670 r678  
    357357  uint64_t unauthorizedTCP; 
    358358  uint64_t tcpClientOverflow; 
     359  uint64_t clientParseError; 
     360  uint64_t serverParseError; 
    359361}; 
    360362