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 : }
|