LCOV - code coverage report
Current view: top level - src - DNS_Mgr.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 168 525 32.0 %
Date: 2010-12-13 Functions: 26 65 40.0 %
Branches: 72 384 18.8 %

           Branch data     Line data    Source code
       1                 :            : // $Id: DNS_Mgr.cc 7073 2010-09-13 00:45:02Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #include <sys/types.h>
       8                 :            : #include <sys/socket.h>
       9                 :            : #ifdef TIME_WITH_SYS_TIME
      10                 :            : # include <sys/time.h>
      11                 :            : # include <time.h>
      12                 :            : #else
      13                 :            : # ifdef HAVE_SYS_TIME_H
      14                 :            : #  include <sys/time.h>
      15                 :            : # else
      16                 :            : #  include <time.h>
      17                 :            : # endif
      18                 :            : #endif
      19                 :            : 
      20                 :            : #include <sys/types.h>
      21                 :            : #include <sys/stat.h>
      22                 :            : #include <unistd.h>
      23                 :            : 
      24                 :            : #include <netinet/in.h>
      25                 :            : 
      26                 :            : #include <errno.h>
      27                 :            : #ifdef HAVE_MEMORY_H
      28                 :            : #include <memory.h>
      29                 :            : #endif
      30                 :            : #include <stdlib.h>
      31                 :            : 
      32                 :            : #include "DNS_Mgr.h"
      33                 :            : #include "Event.h"
      34                 :            : #include "Net.h"
      35                 :            : #include "Var.h"
      36                 :            : 
      37                 :            : extern "C" {
      38                 :            : extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
      39                 :            : 
      40                 :            : #include <netdb.h>
      41                 :            : 
      42                 :            : #include "nb_dns.h"
      43                 :            : }
      44                 :            : 
      45                 :            : 
      46                 :            : class DNS_Mgr_Request {
      47                 :            : public:
      48                 :         57 :         DNS_Mgr_Request(const char* h)  { host = copy_string(h); addr = 0; }
      49                 :          0 :         DNS_Mgr_Request(uint32 a)               { addr = a; host = 0; }
      50         [ +  - ]:         57 :         ~DNS_Mgr_Request()                      { delete [] host; }
      51                 :            : 
      52                 :            :         // Returns nil if this was an address request.
      53                 :        171 :         const char* ReqHost() const     { return host; }
      54                 :          0 :         uint32 ReqAddr() const          { return addr; }
      55                 :            : 
      56                 :            :         int MakeRequest(nb_dns_info* nb_dns);
      57                 :         57 :         int RequestPending() const      { return request_pending; }
      58                 :         57 :         void RequestDone()      { request_pending = 0; }
      59                 :            : 
      60                 :            : 
      61                 :            : protected:
      62                 :            :         char* host;     // if non-nil, this is a host request
      63                 :            :         uint32 addr;
      64                 :            :         int request_pending;
      65                 :            : };
      66                 :            : 
      67                 :         57 : int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns)
      68                 :            :         {
      69         [ -  + ]:         57 :         if ( ! nb_dns )
      70                 :          0 :                 return 0;
      71                 :            : 
      72                 :         57 :         request_pending = 1;
      73                 :            : 
      74                 :            :         char err[NB_DNS_ERRSIZE];
      75         [ +  - ]:         57 :         if ( host )
      76                 :         57 :                 return nb_dns_host_request(nb_dns, host, (void*) this, err) >= 0;
      77                 :            :         else
      78                 :         57 :                 return nb_dns_addr_request(nb_dns, addr, (void*) this, err) >= 0;
      79                 :            :         }
      80                 :            : 
      81                 :            : class DNS_Mapping {
      82                 :            : public:
      83                 :            :         DNS_Mapping(const char* host, struct hostent* h);
      84                 :            :         DNS_Mapping(uint32 addr, struct hostent* h);
      85                 :            :         DNS_Mapping(FILE* f);
      86                 :            : 
      87                 :          0 :         int NoMapping() const           { return no_mapping; }
      88                 :          0 :         int InitFailed() const          { return init_failed; }
      89                 :            : 
      90                 :            :         ~DNS_Mapping();
      91                 :            : 
      92                 :            :         // Returns nil if this was an address request.
      93                 :          0 :         const char* ReqHost() const     { return req_host; }
      94                 :          0 :         uint32 ReqAddr() const          { return req_addr; }
      95                 :            :         const char* ReqStr() const
      96                 :            :                 { return req_host ? req_host : dotted_addr(ReqAddr());  }
      97                 :            : 
      98                 :            :         ListVal* Addrs();
      99                 :            :         TableVal* AddrsSet();   // addresses returned as a set
     100                 :            :         StringVal* Host();
     101                 :            : 
     102                 :          0 :         double CreationTime() const     { return creation_time; }
     103                 :            : 
     104                 :            :         void Save(FILE* f) const;
     105                 :            : 
     106                 :         57 :         int Failed() const              { return failed; }
     107                 :         57 :         int Valid() const               { return ! failed; }
     108                 :            : 
     109                 :            : protected:
     110                 :            :         friend class DNS_Mgr;
     111                 :            : 
     112                 :            :         void Init(struct hostent* h);
     113                 :            :         void Clear();
     114                 :            : 
     115                 :            :         int no_mapping; // when initializing from a file, immediately hit EOF
     116                 :            :         int init_failed;
     117                 :            : 
     118                 :            :         char* req_host;
     119                 :            :         uint32 req_addr;
     120                 :            : 
     121                 :            :         int num_names;
     122                 :            :         char** names;
     123                 :            :         StringVal* host_val;
     124                 :            : 
     125                 :            :         int num_addrs;
     126                 :            :         uint32* addrs;
     127                 :            :         ListVal* addrs_val;
     128                 :            : 
     129                 :            :         int failed;
     130                 :            :         double creation_time;
     131                 :            : };
     132                 :            : 
     133                 :         57 : void DNS_Mgr_mapping_delete_func(void* v)
     134                 :            :         {
     135         [ +  - ]:         57 :         delete (DNS_Mapping*) v;
     136                 :         57 :         }
     137                 :            : 
     138                 :          0 : static TableVal* empty_addr_set()
     139                 :            :         {
     140                 :          0 :         BroType* addr_t = base_type(TYPE_ADDR);
     141                 :          0 :         TypeList* set_index = new TypeList(addr_t);
     142                 :          0 :         set_index->Append(addr_t);
     143                 :          0 :         SetType* s = new SetType(set_index, 0);
     144                 :          0 :         return new TableVal(s);
     145                 :            :         }
     146                 :            : 
     147                 :         57 : DNS_Mapping::DNS_Mapping(const char* host, struct hostent* h)
     148                 :            :         {
     149                 :         57 :         Init(h);
     150                 :         57 :         req_host = copy_string(host);
     151                 :         57 :         req_addr = 0;
     152                 :            : 
     153 [ +  -  +  -  # :         57 :         if ( names && ! names[0] )
              # ][ #  # ]
     154                 :         57 :                 names[0] = copy_string(host);
     155                 :         57 :         }
     156                 :            : 
     157                 :          0 : DNS_Mapping::DNS_Mapping(uint32 addr, struct hostent* h)
     158                 :            :         {
     159                 :          0 :         Init(h);
     160                 :          0 :         req_addr = addr;
     161                 :          0 :         req_host = 0;
     162                 :          0 :         }
     163                 :            : 
     164                 :          0 : DNS_Mapping::DNS_Mapping(FILE* f)
     165                 :            :         {
     166                 :          0 :         Clear();
     167                 :          0 :         init_failed = 1;
     168                 :            : 
     169                 :          0 :         req_host = 0;
     170                 :          0 :         req_addr = 0;
     171                 :            : 
     172                 :            :         char buf[512];
     173                 :            : 
     174   [ #  #  #  # ]:          0 :         if ( ! fgets(buf, sizeof(buf), f) )
     175                 :            :                 {
     176                 :          0 :                 no_mapping = 1;
     177                 :          0 :                 return;
     178                 :            :                 }
     179                 :            : 
     180                 :            :         char req_buf[512+1], name_buf[512+1];
     181                 :            :         int is_req_host;
     182                 :            : 
     183 [ #  # ][ #  # ]:          0 :         if ( sscanf(buf, "%lf %d %512s %d %512s %d", &creation_time, &is_req_host,
     184                 :            :                     req_buf, &failed, name_buf, &num_addrs) != 6 )
     185                 :          0 :                 return;
     186                 :            : 
     187 [ #  # ][ #  # ]:          0 :         if ( is_req_host )
     188                 :          0 :                 req_host = copy_string(req_buf);
     189                 :            :         else
     190                 :          0 :                 req_addr = dotted_to_addr(req_buf);
     191                 :            : 
     192                 :          0 :         num_names = 1;
     193                 :          0 :         names = new char*[num_names];
     194                 :          0 :         names[0] = copy_string(name_buf);
     195                 :            : 
     196   [ #  #  #  # ]:          0 :         if ( num_addrs > 0 )
     197                 :            :                 {
     198                 :          0 :                 addrs = new uint32[num_addrs];
     199                 :            : 
     200 [ #  # ][ #  # ]:          0 :                 for ( int i = 0; i < num_addrs; ++i )
     201                 :            :                         {
     202 [ #  # ][ #  # ]:          0 :                         if ( ! fgets(buf, sizeof(buf), f) )
     203                 :            :                                 {
     204                 :          0 :                                 num_addrs = i;
     205                 :          0 :                                 return;
     206                 :            :                                 }
     207                 :            : 
     208                 :          0 :                         char* newline = strchr(buf, '\n');
     209   [ #  #  #  # ]:          0 :                         if ( newline )
     210                 :          0 :                                 *newline = '\0';
     211                 :            : 
     212                 :          0 :                         addrs[i] = dotted_to_addr(buf);
     213                 :            :                         }
     214                 :            :                 }
     215                 :            :         else
     216                 :          0 :                 addrs = 0;
     217                 :            : 
     218                 :          0 :         init_failed = 0;
     219                 :            :         }
     220                 :            : 
     221                 :         57 : DNS_Mapping::~DNS_Mapping()
     222                 :            :         {
     223 [ +  - ][ #  # ]:         57 :         delete [] req_host;
     224                 :            : 
     225 [ +  - ][ #  # ]:         57 :         if ( names )
     226                 :            :                 {
     227 [ +  + ][ #  # ]:        114 :                 for ( int i = 0; i < num_names; ++i )
     228 [ +  - ][ #  # ]:         57 :                         delete [] names[i];
     229 [ +  - ][ #  # ]:         57 :                 delete [] names;
     230                 :            :                 }
     231                 :            : 
     232 [ +  - ][ #  # ]:         57 :         delete [] addrs;
     233                 :            : 
     234                 :         57 :         Unref(host_val);
     235                 :         57 :         Unref(addrs_val);
     236                 :         57 :         }
     237                 :            : 
     238                 :         57 : ListVal* DNS_Mapping::Addrs()
     239                 :            :         {
     240         [ -  + ]:         57 :         if ( failed )
     241                 :          0 :                 return 0;
     242                 :            : 
     243         [ +  - ]:         57 :         if ( ! addrs_val )
     244                 :            :                 {
     245                 :         57 :                 ListVal* hv = new ListVal(TYPE_ADDR);
     246         [ +  + ]:        114 :                 for ( int i = 0; i < num_addrs; ++i )
     247                 :         57 :                         hv->Append(new AddrVal(addrs[i]));
     248                 :         57 :                 addrs_val = hv;
     249                 :            :                 }
     250                 :            : 
     251                 :         57 :         Ref(addrs_val);
     252                 :         57 :         return addrs_val;
     253                 :            :         }
     254                 :            : 
     255                 :          0 : TableVal* DNS_Mapping::AddrsSet() {
     256                 :          0 :         ListVal* l = Addrs();
     257         [ #  # ]:          0 :         if ( l )
     258                 :          0 :                 return l->ConvertToSet();
     259                 :            :         else
     260                 :          0 :                 return empty_addr_set();
     261                 :            :         }
     262                 :            : 
     263                 :          0 : StringVal* DNS_Mapping::Host()
     264                 :            :         {
     265 [ #  # ][ #  # ]:          0 :         if ( failed || num_names == 0 || ! names[0] )
                 [ #  # ]
     266                 :          0 :                 return 0;
     267                 :            : 
     268         [ #  # ]:          0 :         if ( ! host_val )
     269                 :          0 :                 host_val = new StringVal(names[0]);
     270                 :            : 
     271                 :          0 :         Ref(host_val);
     272                 :          0 :         return host_val;
     273                 :            :         }
     274                 :            : 
     275                 :            : // Converts an array of 4 bytes in network order to the corresponding
     276                 :            : // 32-bit network long.
     277                 :         57 : static uint32 raw_bytes_to_addr(const unsigned char b[4])
     278                 :            :         {
     279                 :         57 :         uint32 l = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
     280                 :         57 :         return uint32(htonl(l));
     281                 :            :         }
     282                 :            : 
     283                 :         57 : void DNS_Mapping::Init(struct hostent* h)
     284                 :            :         {
     285                 :         57 :         no_mapping = 0;
     286                 :         57 :         init_failed = 0;
     287                 :         57 :         creation_time = current_time();
     288                 :         57 :         host_val = 0;
     289                 :         57 :         addrs_val = 0;
     290                 :            : 
     291   [ +  -  +  - ]:         57 :         if ( ! h || h->h_addrtype != AF_INET || h->h_length != 4 )
                 [ -  + ]
     292                 :            :                 {
     293                 :          0 :                 Clear();
     294                 :          0 :                 return;
     295                 :            :                 }
     296                 :            : 
     297                 :         57 :         num_names = 1;  // for now, just use official name
     298                 :         57 :         names = new char*[num_names];
     299         [ -  + ]:         57 :         names[0] = h->h_name ? copy_string(h->h_name) : 0;
     300                 :            : 
     301         [ +  + ]:        114 :         for ( num_addrs = 0; h->h_addr_list[num_addrs]; ++num_addrs )
     302                 :            :                 ;
     303                 :            : 
     304         [ +  - ]:         57 :         if ( num_addrs > 0 )
     305                 :            :                 {
     306                 :         57 :                 addrs = new uint32[num_addrs];
     307         [ +  + ]:        114 :                 for ( int i = 0; i < num_addrs; ++i )
     308                 :            :                         addrs[i] = raw_bytes_to_addr(
     309                 :         57 :                                         (unsigned char*)h->h_addr_list[i]);
     310                 :            :                 }
     311                 :            :         else
     312                 :          0 :                 addrs = 0;
     313                 :            : 
     314                 :         57 :         failed = 0;
     315                 :            :         }
     316                 :            : 
     317                 :          0 : void DNS_Mapping::Clear()
     318                 :            :         {
     319                 :          0 :         num_names = num_addrs = 0;
     320                 :          0 :         names = 0;
     321                 :          0 :         addrs = 0;
     322                 :          0 :         host_val = 0;
     323                 :          0 :         addrs_val = 0;
     324                 :          0 :         no_mapping = 0;
     325                 :          0 :         failed = 1;
     326                 :          0 :         }
     327                 :            : 
     328                 :          0 : void DNS_Mapping::Save(FILE* f) const
     329                 :            :         {
     330                 :            :         fprintf(f, "%.0f %d %s %d %s %d\n", creation_time, req_host != 0,
     331                 :            :                 req_host ? req_host : dotted_addr(req_addr),
     332                 :            :                 failed, (names && names[0]) ? names[0] : "*",
     333 [ #  # ][ #  # ]:          0 :                 num_addrs);
                 [ #  # ]
     334                 :            : 
     335         [ #  # ]:          0 :         for ( int i = 0; i < num_addrs; ++i )
     336                 :          0 :                 fprintf(f, "%s\n", dotted_addr(addrs[i]));
     337                 :          0 :         }
     338                 :            : 
     339                 :            : 
     340                 :          3 : DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode)
     341                 :            :         {
     342                 :          3 :         did_init = 0;
     343                 :            : 
     344                 :          3 :         mode = arg_mode;
     345                 :            : 
     346                 :          3 :         host_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
     347                 :          3 :         addr_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func);
     348                 :            : 
     349                 :            :         char err[NB_DNS_ERRSIZE];
     350                 :          3 :         nb_dns = nb_dns_init(err);
     351                 :            : 
     352   [ -  +  #  # ]:          3 :         if ( ! nb_dns )
     353                 :          0 :                 warn(fmt("problem initializing NB-DNS: %s", err));
     354                 :            : 
     355                 :            :         dns_mapping_valid = dns_mapping_unverified = dns_mapping_new_name =
     356                 :            :                 dns_mapping_lost_name = dns_mapping_name_changed =
     357                 :          3 :                         dns_mapping_altered =  0;
     358                 :            : 
     359                 :          3 :         dm_rec = 0;
     360                 :          3 :         dns_fake_count = 0;
     361                 :            : 
     362                 :          3 :         cache_name = dir = 0;
     363                 :            : 
     364                 :          3 :         asyncs_pending = 0;
     365                 :          3 :         }
     366                 :            : 
     367                 :          2 : DNS_Mgr::~DNS_Mgr()
     368                 :            :         {
     369 [ +  - ][ #  # ]:          2 :         if ( nb_dns )
                 [ #  # ]
     370                 :          2 :                 nb_dns_finish(nb_dns);
     371                 :            : 
     372 [ +  - ][ #  # ]:          2 :         delete [] cache_name;
                 [ #  # ]
     373 [ +  - ][ #  # ]:          2 :         delete [] dir;
                 [ #  # ]
     374 [ +  - ][ #  # ]:          2 :         }
                 [ #  # ]
     375                 :            : 
     376                 :          2 : bool DNS_Mgr::Init()
     377                 :            :         {
     378         [ -  + ]:          2 :         if ( did_init )
     379                 :          0 :                 return true;
     380                 :            : 
     381         [ +  - ]:          2 :         const char* cache_dir = dir ? dir : ".";
     382                 :            : 
     383 [ -  + ][ #  # ]:          2 :         if ( mode == DNS_PRIME && ! ensure_dir(cache_dir) )
                 [ -  + ]
     384                 :            :                 {
     385                 :          0 :                 did_init = 0;
     386                 :          0 :                 return false;
     387                 :            :                 }
     388                 :            : 
     389                 :          2 :         cache_name = new char[strlen(cache_dir) + 64];
     390                 :          2 :         sprintf(cache_name, "%s/%s", cache_dir, ".bro-dns-cache");
     391                 :            : 
     392                 :          2 :         LoadCache(fopen(cache_name, "r"));
     393                 :            : 
     394                 :          2 :         dns_mapping_valid = internal_handler("dns_mapping_valid");
     395                 :          2 :         dns_mapping_unverified = internal_handler("dns_mapping_unverified");
     396                 :          2 :         dns_mapping_new_name = internal_handler("dns_mapping_new_name");
     397                 :          2 :         dns_mapping_lost_name = internal_handler("dns_mapping_lost_name");
     398                 :          2 :         dns_mapping_name_changed = internal_handler("dns_mapping_name_changed");
     399                 :          2 :         dns_mapping_altered = internal_handler("dns_mapping_altered");
     400                 :            : 
     401                 :          2 :         dm_rec = internal_type("dns_mapping")->AsRecordType();
     402                 :            : 
     403                 :          2 :         did_init = 1;
     404                 :            : 
     405                 :          2 :         io_sources.Register(this, true);
     406                 :            : 
     407                 :            :         // We never set idle to false, having the main loop only calling us from
     408                 :            :         // time to time. If we're issuing more DNS requests than we can handle
     409                 :            :         // in this way, we are having problems anyway ...
     410                 :          2 :         idle = true;
     411                 :            : 
     412                 :          2 :         return true;
     413                 :            :         }
     414                 :            : 
     415                 :        114 : TableVal* DNS_Mgr::LookupHost(const char* name)
     416                 :            :         {
     417         [ -  + ]:        114 :         if ( ! nb_dns )
     418                 :          0 :                 return empty_addr_set();
     419                 :            : 
     420         [ +  + ]:        114 :         if ( ! did_init )
     421                 :          2 :                 Init();
     422                 :            : 
     423         [ -  + ]:        114 :         if ( mode == DNS_FAKE )
     424                 :            :                 {
     425                 :          0 :                 ListVal* hv = new ListVal(TYPE_ADDR);
     426                 :          0 :                 hv->Append(new AddrVal(uint32(++dns_fake_count)));
     427                 :          0 :                 return hv->ConvertToSet();
     428                 :            :                 }
     429                 :            : 
     430         [ +  - ]:        114 :         if ( mode != DNS_PRIME )
     431                 :            :                 {
     432                 :        114 :                 DNS_Mapping* d = host_mappings.Lookup(name);
     433                 :            : 
     434         [ +  + ]:        114 :                 if ( d )
     435                 :            :                         {
     436         [ +  - ]:         57 :                         if ( d->Valid() )
     437                 :         57 :                                 return d->Addrs()->ConvertToSet();
     438                 :            :                         else
     439                 :            :                                 {
     440                 :          0 :                                 warn("no such host:", name);
     441                 :          0 :                                 return empty_addr_set();
     442                 :            :                                 }
     443                 :            :                         }
     444                 :            :                 }
     445                 :            : 
     446                 :            :         // Not found, or priming.
     447   [ -  -  +  - ]:         57 :         switch ( mode ) {
     448                 :            :         case DNS_PRIME:
     449                 :          0 :                 requests.append(new DNS_Mgr_Request(name));
     450                 :          0 :                 return empty_addr_set();
     451                 :            : 
     452                 :            :         case DNS_FORCE:
     453                 :          0 :                 internal_error("can't find DNS entry for %s in cache", name);
     454                 :            :                 return 0;
     455                 :            : 
     456                 :            :         case DNS_DEFAULT:
     457                 :         57 :                 requests.append(new DNS_Mgr_Request(name));
     458                 :         57 :                 Resolve();
     459                 :         57 :                 return LookupHost(name);
     460                 :            : 
     461                 :            :         default:
     462                 :        114 :                 internal_error("bad mode in DNS_Mgr::LookupHost");
     463                 :            :                 return 0;
     464                 :            :         }
     465                 :            :         }
     466                 :            : 
     467                 :          0 : Val* DNS_Mgr::LookupAddr(uint32 addr)
     468                 :            :         {
     469         [ #  # ]:          0 :         if ( ! did_init )
     470                 :          0 :                 Init();
     471                 :            : 
     472         [ #  # ]:          0 :         if ( mode != DNS_PRIME )
     473                 :            :                 {
     474                 :          0 :                 HashKey h(&addr, 1);
     475                 :          0 :                 DNS_Mapping* d = addr_mappings.Lookup(&h);
     476                 :            : 
     477         [ #  # ]:          0 :                 if ( d )
     478                 :            :                         {
     479         [ #  # ]:          0 :                         if ( d->Valid() )
     480                 :          0 :                                 return d->Host();
     481                 :            :                         else
     482                 :            :                                 {
     483                 :          0 :                                 warn("can't resolve IP address:", dotted_addr(addr));
     484                 :          0 :                                 return new StringVal(dotted_addr(addr));
     485                 :            :                                 }
     486         [ #  # ]:          0 :                         }
     487                 :            :                 }
     488                 :            : 
     489                 :            :         // Not found, or priming.
     490   [ #  #  #  # ]:          0 :         switch ( mode ) {
     491                 :            :         case DNS_PRIME:
     492                 :          0 :                 requests.append(new DNS_Mgr_Request(addr));
     493                 :          0 :                 return new StringVal("<none>");
     494                 :            : 
     495                 :            :         case DNS_FORCE:
     496                 :            :                 internal_error("can't find DNS entry for %s in cache",
     497                 :          0 :                                 dotted_addr(addr));
     498                 :            :                 return 0;
     499                 :            : 
     500                 :            :         case DNS_DEFAULT:
     501                 :          0 :                 requests.append(new DNS_Mgr_Request(addr));
     502                 :          0 :                 Resolve();
     503                 :          0 :                 return LookupAddr(addr);
     504                 :            : 
     505                 :            :         default:
     506                 :          0 :                 internal_error("bad mode in DNS_Mgr::LookupHost");
     507                 :            :                 return 0;
     508                 :            :         }
     509                 :            :         }
     510                 :            : 
     511                 :          0 : void DNS_Mgr::Verify()
     512                 :            :         {
     513                 :          0 :         }
     514                 :            : 
     515                 :            : #define MAX_PENDING_REQUESTS 20
     516                 :            : 
     517                 :         57 : void DNS_Mgr::Resolve()
     518                 :            :         {
     519         [ -  + ]:         57 :         if ( ! nb_dns )
     520                 :          0 :                 return;
     521                 :            : 
     522                 :            :         int i;
     523                 :            : 
     524                 :         57 :         int first_req = 0;
     525                 :         57 :         int num_pending = min(requests.length(), MAX_PENDING_REQUESTS);
     526                 :         57 :         int last_req = num_pending - 1;
     527                 :            : 
     528                 :            :         // Prime with the initial requests.
     529         [ +  + ]:        114 :         for ( i = first_req; i <= last_req; ++i )
     530                 :         57 :                 requests[i]->MakeRequest(nb_dns);
     531                 :            : 
     532                 :            :         // Start resolving.  Each time an answer comes in, we can issue a
     533                 :            :         // new request, if we have more.
     534         [ +  + ]:        114 :         while ( num_pending > 0 )
     535                 :            :                 {
     536                 :         57 :                 int status = AnswerAvailable(DNS_TIMEOUT);
     537                 :            : 
     538         [ -  + ]:         57 :                 if ( status <= 0 )
     539                 :            :                         {
     540                 :            :                         // Error or timeout.  Process all pending requests as
     541                 :            :                         // unanswered and reprime.
     542         [ #  # ]:          0 :                         for ( i = first_req; i <= last_req; ++i )
     543                 :            :                                 {
     544                 :          0 :                                 DNS_Mgr_Request* dr = requests[i];
     545         [ #  # ]:          0 :                                 if ( dr->RequestPending() )
     546                 :            :                                         {
     547                 :          0 :                                         AddResult(dr, 0);
     548                 :          0 :                                         dr->RequestDone();
     549                 :            :                                         }
     550                 :            :                                 }
     551                 :            : 
     552                 :          0 :                         first_req = last_req + 1;
     553                 :            :                         num_pending = min(requests.length() - first_req,
     554                 :          0 :                                                 MAX_PENDING_REQUESTS);
     555                 :          0 :                         last_req = first_req + num_pending - 1;
     556                 :            : 
     557         [ #  # ]:          0 :                         for ( i = first_req; i <= last_req; ++i )
     558                 :          0 :                                 requests[i]->MakeRequest(nb_dns);
     559                 :            : 
     560                 :          0 :                         continue;
     561                 :            :                         }
     562                 :            : 
     563                 :            :                 char err[NB_DNS_ERRSIZE];
     564                 :            :                 struct nb_dns_result r;
     565                 :         57 :                 status = nb_dns_activity(nb_dns, &r, err);
     566         [ -  + ]:         57 :                 if ( status < 0 )
     567                 :            :                         internal_error(
     568                 :            :                             "NB-DNS error in DNS_Mgr::WaitForReplies (%s)",
     569                 :          0 :                             err);
     570         [ +  - ]:         57 :                 else if ( status > 0 )
     571                 :            :                         {
     572                 :         57 :                         DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie;
     573         [ +  - ]:         57 :                         if ( dr->RequestPending() )
     574                 :            :                                 {
     575                 :         57 :                                 AddResult(dr, &r);
     576                 :         57 :                                 dr->RequestDone();
     577                 :            :                                 }
     578                 :            : 
     579                 :            :                         // Room for another, if we have it.
     580         [ -  + ]:         57 :                         if ( last_req < requests.length() - 1 )
     581                 :            :                                 {
     582                 :          0 :                                 ++last_req;
     583                 :          0 :                                 requests[last_req]->MakeRequest(nb_dns);
     584                 :            :                                 }
     585                 :            :                         else
     586                 :         57 :                                 --num_pending;
     587                 :            :                         }
     588                 :            :                 }
     589                 :            : 
     590                 :            :         // All done with the list of requests.
     591         [ +  + ]:        114 :         for ( i = requests.length() - 1; i >= 0; --i )
     592         [ +  - ]:         57 :                 delete requests.remove_nth(i);
     593                 :            :         }
     594                 :            : 
     595                 :          0 : int DNS_Mgr::Save()
     596                 :            :         {
     597         [ #  # ]:          0 :         if ( ! cache_name )
     598                 :          0 :                 return 0;
     599                 :            : 
     600                 :          0 :         FILE* f = fopen(cache_name, "w");
     601                 :            : 
     602         [ #  # ]:          0 :         if ( ! f )
     603                 :          0 :                 return 0;
     604                 :            : 
     605                 :          0 :         Save(f, host_mappings);
     606                 :          0 :         Save(f, addr_mappings);
     607                 :            : 
     608                 :          0 :         fclose(f);
     609                 :            : 
     610                 :          0 :         return 1;
     611                 :            :         }
     612                 :            : 
     613                 :          0 : void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* dm, ListVal* l1, ListVal* l2)
     614                 :            :         {
     615         [ #  # ]:          0 :         if ( ! e )
     616                 :          0 :                 return;
     617                 :            : 
     618                 :          0 :         val_list* vl = new val_list;
     619                 :          0 :         vl->append(BuildMappingVal(dm));
     620                 :            : 
     621         [ #  # ]:          0 :         if ( l1 )
     622                 :            :                 {
     623                 :          0 :                 vl->append(l1->ConvertToSet());
     624         [ #  # ]:          0 :                 if ( l2 )
     625                 :          0 :                         vl->append(l2->ConvertToSet());
     626                 :            : 
     627                 :          0 :                 Unref(l1);
     628                 :          0 :                 Unref(l2);
     629                 :            :                 }
     630                 :            : 
     631                 :          0 :         mgr.QueueEvent(e, vl);
     632                 :            :         }
     633                 :            : 
     634                 :          0 : void DNS_Mgr::Event(EventHandlerPtr e, DNS_Mapping* old_dm, DNS_Mapping* new_dm)
     635                 :            :         {
     636         [ #  # ]:          0 :         if ( ! e )
     637                 :          0 :                 return;
     638                 :            : 
     639                 :          0 :         val_list* vl = new val_list;
     640                 :          0 :         vl->append(BuildMappingVal(old_dm));
     641                 :          0 :         vl->append(BuildMappingVal(new_dm));
     642                 :          0 :         mgr.QueueEvent(e, vl);
     643                 :            :         }
     644                 :            : 
     645                 :          0 : Val* DNS_Mgr::BuildMappingVal(DNS_Mapping* dm)
     646                 :            :         {
     647                 :          0 :         RecordVal* r = new RecordVal(dm_rec);
     648                 :            : 
     649                 :          0 :         r->Assign(0, new Val(dm->CreationTime(), TYPE_TIME));
     650         [ #  # ]:          0 :         r->Assign(1, new StringVal(dm->ReqHost() ? dm->ReqHost() : ""));
     651                 :          0 :         r->Assign(2, new AddrVal(dm->ReqAddr()));
     652                 :          0 :         r->Assign(3, new Val(dm->Valid(), TYPE_BOOL));
     653                 :            : 
     654                 :          0 :         Val* h = dm->Host();
     655         [ #  # ]:          0 :         r->Assign(4, h ? h : new StringVal("<none>"));
     656                 :          0 :         r->Assign(5, dm->AddrsSet());
     657                 :            : 
     658                 :          0 :         return r;
     659                 :            :         }
     660                 :            : 
     661                 :         57 : void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r)
     662                 :            :         {
     663 [ +  - ][ +  - ]:         57 :         struct hostent* h = (r && r->host_errno == 0) ? r->hostent : 0;
     664                 :            : 
     665                 :            :         DNS_Mapping* new_dm;
     666                 :            :         DNS_Mapping* prev_dm;
     667                 :         57 :         int keep_prev = 0;
     668                 :            : 
     669         [ +  - ]:         57 :         if ( dr->ReqHost() )
     670                 :            :                 {
     671                 :         57 :                 new_dm = new DNS_Mapping(dr->ReqHost(), h);
     672                 :         57 :                 prev_dm = host_mappings.Insert(dr->ReqHost(), new_dm);
     673                 :            : 
     674   [ -  +  #  # ]:         57 :                 if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
         [ #  # ][ -  + ]
     675                 :            :                         {
     676                 :            :                         // Put previous, valid entry back - CompareMappings
     677                 :            :                         // will generate a corresponding warning.
     678                 :          0 :                         (void) host_mappings.Insert(dr->ReqHost(), prev_dm);
     679                 :         57 :                         ++keep_prev;
     680                 :            :                         }
     681                 :            :                 }
     682                 :            :         else
     683                 :            :                 {
     684                 :          0 :                 new_dm = new DNS_Mapping(dr->ReqAddr(), h);
     685                 :          0 :                 uint32 tmp_addr = dr->ReqAddr();
     686                 :          0 :                 HashKey k(&tmp_addr, 1);
     687                 :          0 :                 prev_dm = addr_mappings.Insert(&k, new_dm);
     688                 :            : 
     689   [ #  #  #  # ]:          0 :                 if ( new_dm->Failed() && prev_dm && prev_dm->Valid() )
         [ #  # ][ #  # ]
     690                 :            :                         {
     691                 :          0 :                         uint32 tmp_addr = dr->ReqAddr();
     692                 :          0 :                         HashKey k2(&tmp_addr, 1);
     693                 :          0 :                         (void) addr_mappings.Insert(&k2, prev_dm);
     694                 :          0 :                         ++keep_prev;
     695                 :          0 :                         }
     696                 :            :                 }
     697                 :            : 
     698         [ -  + ]:         57 :         if ( prev_dm )
     699                 :          0 :                 CompareMappings(prev_dm, new_dm);
     700                 :            : 
     701         [ -  + ]:         57 :         if ( keep_prev )
     702         [ #  # ]:          0 :                 delete new_dm;
     703                 :            :         else
     704         [ -  + ]:         57 :                 delete prev_dm;
     705                 :         57 :         }
     706                 :            : 
     707                 :          0 : void DNS_Mgr::CompareMappings(DNS_Mapping* prev_dm, DNS_Mapping* new_dm)
     708                 :            :         {
     709         [ #  # ]:          0 :         if ( prev_dm->Failed() )
     710                 :            :                 {
     711         [ #  # ]:          0 :                 if ( new_dm->Failed() )
     712                 :            :                         // Nothing changed.
     713                 :          0 :                         return;
     714                 :            : 
     715                 :          0 :                 Event(dns_mapping_valid, new_dm);
     716                 :          0 :                 return;
     717                 :            :                 }
     718                 :            : 
     719         [ #  # ]:          0 :         else if ( new_dm->Failed() )
     720                 :            :                 {
     721                 :          0 :                 Event(dns_mapping_unverified, prev_dm);
     722                 :          0 :                 return;
     723                 :            :                 }
     724                 :            : 
     725                 :          0 :         StringVal* prev_s = prev_dm->Host();
     726                 :          0 :         StringVal* new_s = new_dm->Host();
     727                 :            : 
     728   [ #  #  #  # ]:          0 :         if ( prev_s || new_s )
     729                 :            :                 {
     730         [ #  # ]:          0 :                 if ( ! prev_s )
     731                 :          0 :                         Event(dns_mapping_new_name, new_dm);
     732         [ #  # ]:          0 :                 else if ( ! new_s )
     733                 :          0 :                         Event(dns_mapping_lost_name, prev_dm);
     734         [ #  # ]:          0 :                 else if ( ! Bstr_eq(new_s->AsString(), prev_s->AsString()) )
     735                 :          0 :                         Event(dns_mapping_name_changed, prev_dm, new_dm);
     736                 :            : 
     737                 :          0 :                 Unref(prev_s);
     738                 :          0 :                 Unref(new_s);
     739                 :            :                 }
     740                 :            : 
     741                 :          0 :         ListVal* prev_a = prev_dm->Addrs();
     742                 :          0 :         ListVal* new_a = new_dm->Addrs();
     743                 :            : 
     744   [ #  #  #  # ]:          0 :         if ( ! prev_a || ! new_a )
     745                 :          0 :                 internal_error("confused in DNS_Mgr::CompareMappings");
     746                 :            : 
     747                 :          0 :         ListVal* prev_delta = AddrListDelta(prev_a, new_a);
     748                 :          0 :         ListVal* new_delta = AddrListDelta(new_a, prev_a);
     749                 :            : 
     750   [ #  #  #  # ]:          0 :         if ( prev_delta->Length() > 0 || new_delta->Length() > 0 )
                 [ #  # ]
     751                 :          0 :                 Event(dns_mapping_altered, new_dm, prev_delta, new_delta);
     752                 :            :         else
     753                 :            :                 {
     754                 :          0 :                 Unref(prev_delta);
     755                 :          0 :                 Unref(new_delta);
     756                 :            :                 }
     757                 :            :         }
     758                 :            : 
     759                 :          0 : ListVal* DNS_Mgr::AddrListDelta(ListVal* al1, ListVal* al2)
     760                 :            :         {
     761                 :          0 :         ListVal* delta = new ListVal(TYPE_ADDR);
     762                 :            : 
     763         [ #  # ]:          0 :         for ( int i = 0; i < al1->Length(); ++i )
     764                 :            :                 {
     765                 :          0 :                 addr_type al1_i = al1->Index(i)->AsAddr();
     766                 :            : 
     767                 :            :                 int j;
     768         [ #  # ]:          0 :                 for ( j = 0; j < al2->Length(); ++j )
     769                 :            :                         {
     770                 :          0 :                         addr_type al2_j = al2->Index(j)->AsAddr();
     771                 :            : #ifdef BROv6
     772                 :            :                         if ( addr_eq(al1_i, al2_j) )
     773                 :            : #else
     774         [ #  # ]:          0 :                         if ( al1_i == al2_j )
     775                 :            : #endif
     776                 :          0 :                                 break;
     777                 :            :                         }
     778                 :            : 
     779         [ #  # ]:          0 :                 if ( j >= al2->Length() )
     780                 :            :                         // Didn't find it.
     781                 :          0 :                         delta->Append(al1->Index(i)->Ref());
     782                 :            :                 }
     783                 :            : 
     784                 :          0 :         return delta;
     785                 :            :         }
     786                 :            : 
     787                 :          0 : void DNS_Mgr::DumpAddrList(FILE* f, ListVal* al)
     788                 :            :         {
     789         [ #  # ]:          0 :         for ( int i = 0; i < al->Length(); ++i )
     790                 :            :                 {
     791                 :          0 :                 addr_type al_i = al->Index(i)->AsAddr();
     792         [ #  # ]:          0 :                 fprintf(f, "%s%s", i > 0 ? "," : "", dotted_addr(al_i));
     793                 :            :                 }
     794                 :          0 :         }
     795                 :            : 
     796                 :          2 : void DNS_Mgr::LoadCache(FILE* f)
     797                 :            :         {
     798         [ +  - ]:          2 :         if ( ! f )
     799                 :          2 :                 return;
     800                 :            : 
     801                 :          0 :         DNS_Mapping* m = new DNS_Mapping(f);
     802 [ #  # ][ #  # ]:          0 :         for ( ; ! m->NoMapping() && ! m->InitFailed(); m = new DNS_Mapping(f) )
                 [ #  # ]
     803                 :            :                 {
     804         [ #  # ]:          0 :                 if ( m->ReqHost() )
     805                 :          0 :                         host_mappings.Insert(m->ReqHost(), m);
     806                 :            :                 else
     807                 :            :                         {
     808                 :          0 :                         uint32 tmp_addr = m->ReqAddr();
     809                 :          0 :                         HashKey h(&tmp_addr, 1);
     810                 :          0 :                         addr_mappings.Insert(&h, m);
     811                 :            :                         }
     812                 :            :                 }
     813                 :            : 
     814         [ #  # ]:          0 :         if ( ! m->NoMapping() )
     815                 :          0 :                 internal_error("DNS cache corrupted");
     816                 :            : 
     817         [ #  # ]:          0 :         delete m;
     818                 :          2 :         fclose(f);
     819                 :            :         }
     820                 :            : 
     821                 :          0 : void DNS_Mgr::Save(FILE* f, PDict(DNS_Mapping)& m)
     822                 :            :         {
     823                 :          0 :         IterCookie* cookie = m.InitForIteration();
     824                 :            :         DNS_Mapping* dm;
     825                 :            : 
     826         [ #  # ]:          0 :         while ( (dm = m.NextEntry(cookie)) )
     827                 :          0 :                 dm->Save(f);
     828                 :          0 :         }
     829                 :            : 
     830                 :          0 : const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr)
     831                 :            :         {
     832                 :          0 :         HashKey h(&addr, 1);
     833                 :          0 :         DNS_Mapping* d = dns_mgr->addr_mappings.Lookup(&h);
     834         [ #  # ]:          0 :         if ( ! d )
     835                 :          0 :                 return 0;
     836                 :            : 
     837                 :            :         // The escapes in the following strings are to avoid having it
     838                 :            :         // interpreted as a trigraph sequence.
     839         [ #  # ]:          0 :         return d->names ? d->names[0] : "<\?\?\?>";
     840                 :            :         }
     841                 :            : 
     842                 :          0 : TableVal* DNS_Mgr::LookupNameInCache(string name)
     843                 :            :         {
     844                 :          0 :         DNS_Mapping* d = dns_mgr->host_mappings.Lookup(name.c_str());
     845   [ #  #  #  # ]:          0 :         if ( ! d || ! d->names )
     846                 :          0 :                 return 0;
     847                 :            : 
     848                 :          0 :         return d->AddrsSet();
     849                 :            :         }
     850                 :            : 
     851                 :          0 : void DNS_Mgr::AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback)
     852                 :            :         {
     853         [ #  # ]:          0 :         if ( ! did_init )
     854                 :          0 :                 Init();
     855                 :            : 
     856                 :            :         // Do we already know the answer?
     857                 :          0 :         const char* name = LookupAddrInCache(host);
     858         [ #  # ]:          0 :         if ( name )
     859                 :            :                 {
     860                 :          0 :                 callback->Resolved(name);
     861         [ #  # ]:          0 :                 delete callback;
     862                 :          0 :                 return;
     863                 :            :                 }
     864                 :            : 
     865                 :          0 :         AsyncRequest* req = 0;
     866                 :            : 
     867                 :            :         // Have we already a request waiting for this host?
     868                 :          0 :         AsyncRequestAddrMap::iterator i = asyncs_addrs.find(host);
     869         [ #  # ]:          0 :         if ( i != asyncs_addrs.end() )
     870                 :          0 :                 req = i->second;
     871                 :            :         else
     872                 :            :                 {
     873                 :            :                 // A new one.
     874                 :          0 :                 req = new AsyncRequest;
     875                 :          0 :                 req->host = host;
     876                 :          0 :                 asyncs_queued.push_back(req);
     877                 :          0 :                 asyncs_addrs.insert(AsyncRequestAddrMap::value_type(host, req));
     878                 :            :                 }
     879                 :            : 
     880                 :          0 :         req->callbacks.push_back(callback);
     881                 :            : 
     882                 :          0 :         IssueAsyncRequests();
     883                 :            :         }
     884                 :            : 
     885                 :          0 : void DNS_Mgr::AsyncLookupName(string name, LookupCallback* callback)
     886                 :            :         {
     887         [ #  # ]:          0 :         if ( ! did_init )
     888                 :          0 :                 Init();
     889                 :            : 
     890                 :            :         // Do we already know the answer?
     891                 :          0 :         TableVal* addrs = LookupNameInCache(name);
     892         [ #  # ]:          0 :         if ( addrs )
     893                 :            :                 {
     894                 :          0 :                 callback->Resolved(addrs);
     895                 :          0 :                 Unref(addrs);
     896         [ #  # ]:          0 :                 delete callback;
     897                 :          0 :                 return;
     898                 :            :                 }
     899                 :            : 
     900                 :          0 :         AsyncRequest* req = 0;
     901                 :            : 
     902                 :            :         // Have we already a request waiting for this host?
     903                 :          0 :         AsyncRequestNameMap::iterator i = asyncs_names.find(name);
     904         [ #  # ]:          0 :         if ( i != asyncs_names.end() )
     905                 :          0 :                 req = i->second;
     906                 :            :         else
     907                 :            :                 {
     908                 :            :                 // A new one.
     909                 :          0 :                 req = new AsyncRequest;
     910                 :          0 :                 req->name = name;
     911                 :          0 :                 asyncs_queued.push_back(req);
     912                 :          0 :                 asyncs_names.insert(AsyncRequestNameMap::value_type(name, req));
     913                 :            :                 }
     914                 :            : 
     915                 :          0 :         req->callbacks.push_back(callback);
     916                 :            : 
     917                 :          0 :         IssueAsyncRequests();
     918                 :            :         }
     919                 :            : 
     920                 :          0 : void DNS_Mgr::IssueAsyncRequests()
     921                 :            :         {
     922 [ #  # ][ #  # ]:          0 :         while ( asyncs_queued.size() && asyncs_pending < MAX_PENDING_REQUESTS )
                 [ #  # ]
     923                 :            :                 {
     924                 :          0 :                 AsyncRequest* req = asyncs_queued.front();
     925                 :          0 :                 asyncs_queued.pop_front();
     926                 :            : 
     927                 :            :                 DNS_Mgr_Request* dr;
     928         [ #  # ]:          0 :                 if ( req->IsAddrReq() )
     929                 :          0 :                         dr = new DNS_Mgr_Request(req->host);
     930                 :            :                 else
     931                 :          0 :                         dr = new DNS_Mgr_Request(req->name.c_str());
     932                 :            : 
     933         [ #  # ]:          0 :                 if ( ! dr->MakeRequest(nb_dns) )
     934                 :            :                         {
     935                 :          0 :                         run_time("can't issue DNS request");
     936                 :          0 :                         req->Timeout();
     937                 :          0 :                         continue;
     938                 :            :                         }
     939                 :            : 
     940                 :          0 :                 req->time = current_time();
     941                 :          0 :                 asyncs_timeouts.push(req);
     942                 :            : 
     943                 :          0 :                 ++asyncs_pending;
     944                 :            :                 }
     945                 :          0 :         }
     946                 :            : 
     947                 :        855 : void  DNS_Mgr::GetFds(int* read, int* write, int* except)
     948                 :            :         {
     949                 :        855 :         *read = nb_dns_fd(nb_dns);
     950                 :        855 :         }
     951                 :            : 
     952                 :        845 : double DNS_Mgr::NextTimestamp(double* network_time)
     953                 :            :         {
     954                 :            :         // This is kind of cheating ...
     955         [ -  + ]:        845 :         return asyncs_timeouts.size() ? timer_mgr->Time() : -1.0;
     956                 :            :         }
     957                 :            : 
     958                 :          0 : void DNS_Mgr::CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout)
     959                 :            :         {
     960                 :            :         // Note that this code is a mirror of that for CheckAsyncHostRequest.
     961                 :            : 
     962                 :            :         // In the following, if it's not in the respective map anymore, we've
     963                 :            :         // already finished it earlier and don't have anything to do.
     964                 :          0 :         AsyncRequestAddrMap::iterator i = asyncs_addrs.find(addr);
     965                 :            : 
     966         [ #  # ]:          0 :         if ( i != asyncs_addrs.end() )
     967                 :            :                 {
     968                 :          0 :                 const char* name = LookupAddrInCache(addr);
     969         [ #  # ]:          0 :                 if ( name )
     970                 :          0 :                         i->second->Resolved(name);
     971                 :            : 
     972         [ #  # ]:          0 :                 else if ( timeout )
     973                 :          0 :                         i->second->Timeout();
     974                 :            : 
     975                 :            :                 else
     976                 :          0 :                         return;
     977                 :            : 
     978                 :          0 :                 asyncs_addrs.erase(i);
     979                 :          0 :                 --asyncs_pending;
     980                 :            : 
     981                 :            :                 // Don't delete the request.  That will be done once it
     982                 :            :                 // eventually times out.
     983                 :            :                 }
     984                 :            : 
     985                 :            :         }
     986                 :            : 
     987                 :          0 : void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout)
     988                 :            :         {
     989                 :            :         // Note that this code is a mirror of that for CheckAsyncAddrRequest.
     990                 :            : 
     991                 :          0 :         AsyncRequestNameMap::iterator i = asyncs_names.find(host);
     992                 :            : 
     993         [ #  # ]:          0 :         if ( i != asyncs_names.end() )
     994                 :            :                 {
     995                 :          0 :                 TableVal* addrs = LookupNameInCache(host);
     996                 :            : 
     997         [ #  # ]:          0 :                 if ( addrs )
     998                 :            :                         {
     999                 :          0 :                         i->second->Resolved(addrs);
    1000                 :          0 :                         Unref(addrs);
    1001                 :            :                         }
    1002                 :            : 
    1003         [ #  # ]:          0 :                 else if ( timeout )
    1004                 :          0 :                         i->second->Timeout();
    1005                 :            : 
    1006                 :            :                 else
    1007                 :          0 :                         return;
    1008                 :            : 
    1009                 :          0 :                 asyncs_names.erase(i);
    1010                 :          0 :                 --asyncs_pending;
    1011                 :            : 
    1012                 :            :                 // Don't delete the request.  That will be done once it
    1013                 :            :                 // eventually times out.
    1014                 :            :                 }
    1015                 :            :         }
    1016                 :            : 
    1017                 :          0 : void  DNS_Mgr::Process()
    1018                 :            :         {
    1019                 :            : 
    1020         [ #  # ]:          0 :         while ( asyncs_timeouts.size() > 0 )
    1021                 :            :                 {
    1022                 :          0 :                 AsyncRequest* req = asyncs_timeouts.top();
    1023                 :            : 
    1024         [ #  # ]:          0 :                 if ( req->time + DNS_TIMEOUT > current_time() )
    1025                 :          0 :                         break;
    1026                 :            : 
    1027         [ #  # ]:          0 :                 if ( req->IsAddrReq() )
    1028                 :          0 :                         CheckAsyncAddrRequest(req->host, true);
    1029                 :            :                 else
    1030                 :          0 :                         CheckAsyncHostRequest(req->name.c_str(), true);
    1031                 :            : 
    1032                 :          0 :                 asyncs_timeouts.pop();
    1033         [ #  # ]:          0 :                 delete req;
    1034                 :            :                 }
    1035                 :            : 
    1036 [ #  # ][ #  # ]:          0 :         if ( asyncs_addrs.size() == 0 && asyncs_names.size() == 0 )
                 [ #  # ]
    1037                 :          0 :                 return;
    1038                 :            : 
    1039         [ #  # ]:          0 :         if ( AnswerAvailable(0) <= 0 )
    1040                 :          0 :                 return;
    1041                 :            : 
    1042                 :            :         char err[NB_DNS_ERRSIZE];
    1043                 :            :         struct nb_dns_result r;
    1044                 :            : 
    1045                 :          0 :         int status = nb_dns_activity(nb_dns, &r, err);
    1046                 :            : 
    1047         [ #  # ]:          0 :         if ( status < 0 )
    1048                 :          0 :                 internal_error("NB-DNS error in DNS_Mgr::Process (%s)", err);
    1049                 :            : 
    1050         [ #  # ]:          0 :         else if ( status > 0 )
    1051                 :            :                 {
    1052                 :          0 :                 DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie;
    1053         [ #  # ]:          0 :                 if ( dr->RequestPending() )
    1054                 :            :                         {
    1055                 :          0 :                         AddResult(dr, &r);
    1056                 :          0 :                         dr->RequestDone();
    1057                 :            :                         }
    1058                 :            : 
    1059         [ #  # ]:          0 :                 if ( ! dr->ReqHost() )
    1060                 :          0 :                         CheckAsyncAddrRequest(dr->ReqAddr(), true);
    1061                 :            :                 else
    1062                 :          0 :                         CheckAsyncHostRequest(dr->ReqHost(), true);
    1063                 :            : 
    1064                 :          0 :                 IssueAsyncRequests();
    1065                 :            :                 }
    1066                 :            :         }
    1067                 :            : 
    1068                 :         57 : int DNS_Mgr::AnswerAvailable(int timeout)
    1069                 :            :         {
    1070                 :         57 :         int fd = nb_dns_fd(nb_dns);
    1071         [ -  + ]:         57 :         if ( fd < 0 )
    1072                 :          0 :                 internal_error("nb_dns_fd() failed in DNS_Mgr::WaitForReplies");
    1073                 :            : 
    1074                 :            :         fd_set read_fds;
    1075                 :            : 
    1076                 :         57 :         FD_ZERO(&read_fds);
    1077                 :         57 :         FD_SET(fd, &read_fds);
    1078                 :            : 
    1079                 :            :         struct timeval t;
    1080                 :         57 :         t.tv_sec = timeout;
    1081                 :         57 :         t.tv_usec = 0;
    1082                 :            : 
    1083                 :         57 :         int status = select(fd+1, &read_fds, 0, 0, &t);
    1084                 :            : 
    1085         [ -  + ]:         57 :         if ( status < 0 )
    1086                 :            :                 {
    1087         [ #  # ]:          0 :                 if ( errno == EINTR )
    1088                 :          0 :                         return -1;
    1089                 :          0 :                 internal_error("problem with DNS select");
    1090                 :            :                 }
    1091                 :            : 
    1092         [ -  + ]:         57 :         if ( status > 1 )
    1093                 :          0 :                 internal_error("strange return from DNS select");
    1094                 :            : 
    1095                 :         57 :         return status;
    1096 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8