root/src/noit_check_resolver.c

Revision a23f47e7bb070a6655626159e9150216989a9614, 18.2 kB (checked in by Philip Maddox <pmaddox@circonus.com>, 5 months ago)

Fix Broken DNS TTL Handling

TTL handling for DNS lookups was somewhat broken. We would do two DNS
lookups for each target - an IPv4 and an IPv6. We would end up setting
the TTL to whatever the second result to come back was; so, if we got a
valid IPv4 result, but an invalid IPv6 result, we would override the
TTL with the default value, 60 seconds.

Now, only set the default value if the other resolver is still in-flight...
This will fix the issue where the second result comes back and is invalid,
causing us to ignore the first TTL result.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2011, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name OmniTI Computer Consulting, Inc. nor the names
16  *       of its contributors may be used to endorse or promote products
17  *       derived from this software without specific prior written
18  *       permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 #include "noit_defines.h"
34
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <unistd.h>
38 #include <time.h>
39 #include <ctype.h>
40 #include <assert.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44
45 #include "eventer/eventer.h"
46 #include "utils/noit_log.h"
47 #include "utils/noit_skiplist.h"
48 #include "utils/noit_hash.h"
49 #include "udns/udns.h"
50 #include "noit_console.h"
51
52 #define MAX_RR 256
53 #define DEFAULT_FAILED_TTL 60
54 #define DEFAULT_PURGE_AGE  1200 /* 20 minutes */
55
56 static struct dns_ctx *dns_ctx;
57 static noit_skiplist nc_dns_cache;
58 static eventer_t dns_cache_timeout = NULL;
59 static noit_hash_table etc_hosts_cache;
60
61 typedef struct {
62   time_t last_needed;
63   time_t last_updated;
64   noit_boolean lookup_inflight_v4;
65   noit_boolean lookup_inflight_v6;
66   char *target;
67   unsigned char dn[DNS_MAXDN];
68   time_t ttl;
69   int ip4_cnt;
70   char **ip4;
71   int ip6_cnt;
72   char **ip6;
73 } dns_cache_node;
74
75 typedef struct {
76   char *target;
77   struct in_addr ip4;
78   struct in6_addr ip6;
79   int has_ip4:1;
80   int has_ip6:1;
81 } static_host_node;
82
83 void dns_cache_node_free(void *vn) {
84   dns_cache_node *n = vn;
85   int i;
86   if(!n) return;
87   if(n->target) free(n->target);
88   for(i=0;i<n->ip4_cnt;i++) if(n->ip4[i]) free(n->ip4[i]);
89   for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]);
90   if(n->ip4) free(n->ip4);
91   if(n->ip6) free(n->ip6);
92   free(n);
93 }
94
95 static int name_lookup(const void *av, const void *bv) {
96   const dns_cache_node *a = av;
97   const dns_cache_node *b = bv;
98   return strcmp(a->target, b->target);
99 }
100 static int name_lookup_k(const void *akv, const void *bv) {
101   const char *ak = akv;
102   const dns_cache_node *b = bv;
103   return strcmp(ak, b->target);
104 }
105 static int refresh_idx(const void *av, const void *bv) {
106   const dns_cache_node *a = av;
107   const dns_cache_node *b = bv;
108   if((a->last_updated + a->ttl) < (b->last_updated + b->ttl)) return -1;
109   return 1;
110 }
111 static int refresh_idx_k(const void *akv, const void *bv) {
112   time_t f = (time_t) akv;
113   const dns_cache_node *b = bv;
114   if(f < (b->last_updated + b->ttl)) return -1;
115   return 1;
116 }
117
118 void noit_check_resolver_remind(const char *target) {
119   dns_cache_node *n;
120   if(!target) return;
121   n = noit_skiplist_find(&nc_dns_cache, target, NULL);
122   if(n != NULL) {
123     n->last_needed = time(NULL);
124     return;
125   }
126   n = calloc(1, sizeof(*n));
127   n->target = strdup(target);
128   n->last_needed = time(NULL);
129   noit_skiplist_insert(&nc_dns_cache, n);
130 }
131
132
133 int noit_check_resolver_fetch(const char *target, char *buff, int len,
134                               uint8_t prefer_family) {
135   int i;
136   uint8_t progression[2];
137   dns_cache_node *n;
138   void *vnode;
139
140   buff[0] = '\0';
141   if(!target) return -1;
142   progression[0] = prefer_family;
143   progression[1] = (prefer_family == AF_INET) ? AF_INET6 : AF_INET;
144
145   if(noit_hash_retrieve(&etc_hosts_cache, target, strlen(target), &vnode)) {
146     static_host_node *node = vnode;
147     for(i=0; i<2; i++) {
148       switch(progression[i]) {
149         case AF_INET:
150           if(node->has_ip4) {
151             inet_ntop(AF_INET, &node->ip4, buff, len);
152             return 1;
153           }
154           break;
155         case AF_INET6:
156           if(node->has_ip6) {
157             inet_ntop(AF_INET6, &node->ip6, buff, len);
158             return 1;
159           }
160           break;
161       }
162     }
163   }
164
165   n = noit_skiplist_find(&nc_dns_cache, target, NULL);
166   if(n != NULL) {
167     int rv;
168     if(n->last_updated == 0) return -1; /* not resolved yet */
169     rv = n->ip4_cnt + n->ip6_cnt;
170     for(i=0; i<2; i++) {
171       switch(progression[i]) {
172         case AF_INET:
173           if(n->ip4_cnt > 0) {
174             strlcpy(buff, n->ip4[0], len);
175             return rv;
176           }
177           break;
178         case AF_INET6:
179           if(n->ip6_cnt > 0) {
180             strlcpy(buff, n->ip6[0], len);
181             return rv;
182           }
183           break;
184       }
185     }
186     return rv;
187   }
188   return -1;
189 }
190
191 static void blank_update_v4(dns_cache_node *n) {
192   int i;
193   for(i=0;i<n->ip4_cnt;i++) if(n->ip4[i]) free(n->ip4[i]);
194   if(n->ip4) free(n->ip4);
195   n->ip4 = NULL;
196   n->ip4_cnt = 0;
197   noit_skiplist_remove(&nc_dns_cache, n->target, NULL);
198   n->last_updated = time(NULL);
199   if (n->lookup_inflight_v6) {
200     n->ttl = DEFAULT_FAILED_TTL;
201   }
202   n->lookup_inflight_v4 = noit_false;
203   noit_skiplist_insert(&nc_dns_cache, n);
204 }
205 static void blank_update_v6(dns_cache_node *n) {
206   int i;
207   for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]);
208   if(n->ip6) free(n->ip6);
209   n->ip6 = NULL;
210   n->ip6_cnt = 0;
211   noit_skiplist_remove(&nc_dns_cache, n->target, NULL);
212   n->last_updated = time(NULL);
213   if (n->lookup_inflight_v4) {
214     n->ttl = DEFAULT_FAILED_TTL;
215   }
216   n->lookup_inflight_v6 = noit_false;
217   noit_skiplist_insert(&nc_dns_cache, n);
218 }
219 static void blank_update(dns_cache_node *n) {
220   blank_update_v4(n);
221   blank_update_v6(n);
222 }
223
224 static int dns_cache_callback(eventer_t e, int mask, void *closure,
225                               struct timeval *now) {
226   struct dns_ctx *ctx = closure;
227   dns_ioevent(ctx, now->tv_sec);
228   return EVENTER_READ | EVENTER_EXCEPTION;
229 }
230
231 static int dns_invoke_timeouts(eventer_t e, int mask, void *closure,
232                                struct timeval *now) {
233   struct dns_ctx *ctx = closure;
234   dns_timeouts(ctx, 0, now->tv_sec);
235   return 0;
236 }
237
238 static void dns_cache_utm_fn(struct dns_ctx *ctx, int timeout, void *data) {
239   eventer_t e = NULL, newe = NULL;
240   if(ctx == NULL) e = eventer_remove(dns_cache_timeout);
241   else {
242     if(timeout < 0) e = eventer_remove(dns_cache_timeout);
243     else {
244       newe = eventer_alloc();
245       newe->mask = EVENTER_TIMER;
246       newe->callback = dns_invoke_timeouts;
247       newe->closure = dns_ctx;
248       gettimeofday(&newe->whence, NULL);
249       newe->whence.tv_sec += timeout;
250     }
251   }
252   if(e) eventer_free(e);
253   if(newe) eventer_add(newe);
254   dns_cache_timeout = newe;
255 }
256
257 static void dns_cache_resolve(struct dns_ctx *ctx, void *result, void *data,
258                               enum dns_type rtype) {
259   int i, ttl, acnt, r = dns_status(ctx);
260   dns_cache_node *n = data;
261   unsigned char idn[DNS_MAXDN], dn[DNS_MAXDN];
262   struct dns_parse p;
263   struct dns_rr rr;
264   unsigned nrr;
265   char **answers;
266   const unsigned char *pkt, *cur, *end;
267
268   if(!result) goto blank;
269
270   dns_dntodn(n->dn, idn, sizeof(idn));
271
272   pkt = result; end = pkt + r; cur = dns_payload(pkt);
273   dns_getdn(pkt, &cur, end, dn, sizeof(dn));
274   dns_initparse(&p, NULL, pkt, cur, end);
275   p.dnsp_qcls = 0;
276   p.dnsp_qtyp = 0;
277   nrr = 0;
278   ttl = 0;
279
280   while((r = dns_nextrr(&p, &rr)) > 0) {
281     if (!dns_dnequal(idn, rr.dnsrr_dn)) continue;
282     if (DNS_C_IN == rr.dnsrr_cls && rtype == rr.dnsrr_typ) ++nrr;
283     else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
284       if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
285                     p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
286           rr.dnsrr_dptr != rr.dnsrr_dend) {
287         break;
288       }
289       else {
290         if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
291           ttl = rr.dnsrr_ttl;
292         dns_dntodn(p.dnsp_dnbuf, idn, sizeof(idn));
293       }
294     }
295   }
296   if(!r && !nrr) goto blank;
297
298   dns_rewind(&p, NULL);
299   p.dnsp_qcls = DNS_C_IN;
300   p.dnsp_qtyp = rtype;
301   answers = calloc(nrr, sizeof(*answers));
302   acnt = 0;
303   while(dns_nextrr(&p, &rr) && nrr < MAX_RR) {
304     char buff[INET6_ADDRSTRLEN];
305     if (!dns_dnequal(idn, rr.dnsrr_dn)) continue;
306     if (p.dnsp_rrl && !rr.dnsrr_dn[0] && rr.dnsrr_typ == DNS_T_OPT) continue;
307     if (rtype == rr.dnsrr_typ) {
308       if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
309         ttl = rr.dnsrr_ttl;
310       switch(rr.dnsrr_typ) {
311         case DNS_T_A:
312           if(rr.dnsrr_dsz != 4) continue;
313           inet_ntop(AF_INET, rr.dnsrr_dptr, buff, sizeof(buff));
314           answers[acnt++] = strdup(buff);
315           break;
316         case DNS_T_AAAA:
317           if(rr.dnsrr_dsz != 16) continue;
318           inet_ntop(AF_INET6, rr.dnsrr_dptr, buff, sizeof(buff));
319           answers[acnt++] = strdup(buff);
320           break;
321         default:
322           break;
323       }
324     }
325   }
326
327   n->ttl = ttl;
328   if(rtype == DNS_T_A) {
329     for(i=0;i<n->ip4_cnt;i++) if(n->ip4[i]) free(n->ip4[i]);
330     if(n->ip4) free(n->ip4);
331     n->ip4_cnt = acnt;
332     n->ip4 = answers;
333     n->lookup_inflight_v4 = noit_false;
334   }
335   else if(rtype == DNS_T_AAAA) {
336     for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]);
337     if(n->ip6) free(n->ip6);
338     n->ip6_cnt = acnt;
339     n->ip6 = answers;
340     n->lookup_inflight_v6 = noit_false;
341   }
342   else {
343     if(answers) free(answers);
344     if(result) free(result);
345      return;
346   }
347   noit_skiplist_remove(&nc_dns_cache, n->target, NULL);
348   n->last_updated = time(NULL);
349   noit_skiplist_insert(&nc_dns_cache, n);
350   noitL(noit_debug, "Resolved %s/%s -> %d records\n", n->target,
351         (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")),
352         acnt);
353   if(result) free(result);
354   return;
355
356  blank:
357   if(rtype == DNS_T_A) blank_update_v4(n);
358   if(rtype == DNS_T_AAAA) blank_update_v6(n);
359   noitL(noit_debug, "Resolved %s/%s -> blank\n", n->target,
360         (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")));
361   if(result) free(result);
362   return;
363 }
364 static void dns_cache_resolve_v4(struct dns_ctx *ctx, void *result, void *data) {
365   dns_cache_resolve(ctx, result, data, DNS_T_A);
366 }
367 static void dns_cache_resolve_v6(struct dns_ctx *ctx, void *result, void *data) {
368   dns_cache_resolve(ctx, result, data, DNS_T_AAAA);
369 }
370
371 void noit_check_resolver_maintain() {
372   time_t now;
373   noit_skiplist *tlist;
374   noit_skiplist_node *sn;
375
376   now = time(NULL);
377   sn = noit_skiplist_getlist(nc_dns_cache.index);
378   assert(sn);
379   tlist = sn->data;
380   assert(tlist);
381   sn = noit_skiplist_getlist(tlist);
382   while(sn) {
383     dns_cache_node *n = sn->data;
384     noit_skiplist_next(tlist, &sn); /* move forward */
385     /* remove if needed */
386     if(n->last_updated + n->ttl > now) break;
387     if(n->last_needed + DEFAULT_PURGE_AGE < now &&
388        !(n->lookup_inflight_v4 || n->lookup_inflight_v6))
389       noit_skiplist_remove(&nc_dns_cache, n->target, dns_cache_node_free);
390     else {
391       int abs;
392       if(!dns_ptodn(n->target, strlen(n->target),
393                     n->dn, sizeof(n->dn), &abs)) {
394         blank_update(n);
395       }
396       else {
397         if(!n->lookup_inflight_v4) {
398           n->lookup_inflight_v4 = noit_true;
399           if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_A,
400                             abs | DNS_NOSRCH, NULL, dns_cache_resolve_v4, n))
401             blank_update_v4(n);
402           else
403             dns_timeouts(dns_ctx, -1, now);
404         }
405         if(!n->lookup_inflight_v6) {
406           n->lookup_inflight_v6 = noit_true;
407           if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_AAAA,
408                             abs | DNS_NOSRCH, NULL, dns_cache_resolve_v6, n))
409             blank_update_v6(n);
410           else
411             dns_timeouts(dns_ctx, -1, now);
412         }
413       }
414       noitL(noit_debug, "Firing lookup for '%s'\n", n->target);
415       continue;
416     }
417   }
418 }
419
420 int noit_check_resolver_loop(eventer_t e, int mask, void *c,
421                              struct timeval *now) {
422   noit_check_resolver_maintain();
423   eventer_add_in_s_us(noit_check_resolver_loop, NULL, 1, 0);
424   return 0;
425 }
426
427 static int
428 nc_print_dns_cache_node(noit_console_closure_t ncct,
429                         const char *target, dns_cache_node *n) {
430   nc_printf(ncct, "==== %s ====\n", target);
431   if(!n) nc_printf(ncct, "NOT FOUND\n");
432   else {
433     int i;
434     time_t now = time(NULL);
435     nc_printf(ncct, "%16s: %ds ago\n", "last needed", now - n->last_needed);
436     nc_printf(ncct, "%16s: %ds ago\n", "resolved", now - n->last_updated);
437     nc_printf(ncct, "%16s: %ds\n", "ttl", n->ttl);
438     if(n->lookup_inflight_v4) nc_printf(ncct, "actively resolving A RRs\n");
439     if(n->lookup_inflight_v6) nc_printf(ncct, "actively resolving AAAA RRs\n");
440     for(i=0;i<n->ip4_cnt;i++)
441       nc_printf(ncct, "%17s %s\n", i?"":"IPv4:", n->ip4[i]);
442     for(i=0;i<n->ip6_cnt;i++)
443       nc_printf(ncct, "%17s %s\n", i?"":"IPv6:", n->ip6[i]);
444   }
445   return 0;
446 }
447 static int
448 noit_console_show_dns_cache(noit_console_closure_t ncct,
449                             int argc, char **argv,
450                             noit_console_state_t *dstate,
451                             void *closure) {
452   int i;
453
454   if(argc == 0) {
455     noit_skiplist_node *sn;
456     for(sn = noit_skiplist_getlist(&nc_dns_cache); sn;
457         noit_skiplist_next(&nc_dns_cache, &sn)) {
458       dns_cache_node *n = (dns_cache_node *)sn->data;
459       nc_print_dns_cache_node(ncct, n->target, n);
460     }
461   }
462   for(i=0;i<argc;i++) {
463     dns_cache_node *n;
464     n = noit_skiplist_find(&nc_dns_cache, argv[i], NULL);
465     nc_print_dns_cache_node(ncct, argv[i], n);
466   }
467   return 0;
468 }
469 static int
470 noit_console_manip_dns_cache(noit_console_closure_t ncct,
471                              int argc, char **argv,
472                              noit_console_state_t *dstate,
473                              void *closure) {
474   int i;
475   if(argc == 0) {
476     nc_printf(ncct, "dns_cache what?\n");
477     return 0;
478   }
479   if(closure == NULL) {
480     /* adding */
481     for(i=0;i<argc;i++) {
482       dns_cache_node *n;
483       if(NULL != (n = noit_skiplist_find(&nc_dns_cache, argv[i], NULL))) {
484         nc_printf(ncct, " == Already in system ==\n");
485         nc_print_dns_cache_node(ncct, argv[i], n);
486       }
487       else {
488         nc_printf(ncct, "%s submitted.\n", argv[i]);
489         noit_check_resolver_remind(argv[i]);
490       }
491     }
492   }
493   else {
494     for(i=0;i<argc;i++) {
495       dns_cache_node *n;
496       if(NULL != (n = noit_skiplist_find(&nc_dns_cache, argv[i], NULL))) {
497         if(n->lookup_inflight_v4 || n->lookup_inflight_v6)
498           nc_printf(ncct, "%s is currently resolving and cannot be removed.\n");
499         else {
500           noit_skiplist_remove(&nc_dns_cache, argv[i], dns_cache_node_free);
501           nc_printf(ncct, "%s removed.\n", argv[i]);
502         }
503       }
504       else nc_printf(ncct, "%s not in system.\n", argv[i]);
505     }
506   }
507   return 0;
508 }
509
510 static void
511 register_console_dns_cache_commands() {
512   noit_console_state_t *tl;
513   cmd_info_t *showcmd, *nocmd;
514
515   tl = noit_console_state_initial();
516   showcmd = noit_console_state_get_cmd(tl, "show");
517   assert(showcmd && showcmd->dstate);
518
519   nocmd = noit_console_state_get_cmd(tl, "no");
520   assert(nocmd && nocmd->dstate);
521
522   noit_console_state_add_cmd(showcmd->dstate,
523     NCSCMD("dns_cache", noit_console_show_dns_cache, NULL, NULL, NULL));
524
525   noit_console_state_add_cmd(tl,
526     NCSCMD("dns_cache", noit_console_manip_dns_cache, NULL, NULL, NULL));
527
528   noit_console_state_add_cmd(nocmd->dstate,
529     NCSCMD("dns_cache", noit_console_manip_dns_cache, NULL, NULL, (void *)0x1));
530 }
531
532 int
533 noit_check_etc_hosts_cache_refresh(eventer_t e, int mask, void *closure,
534                                    struct timeval *now) {
535   static struct stat last_stat;
536   struct stat sb;
537   struct hostent *ent;
538   int reload = 0;
539
540   memset(&sb, 0, sizeof(sb));
541   stat("/etc/hosts", &sb);
542 #define CSTAT(f) (sb.f == last_stat.f)
543   reload = ! (CSTAT(st_dev) && CSTAT(st_ino) && CSTAT(st_mode) && CSTAT(st_uid) &&
544               CSTAT(st_gid) && CSTAT(st_size) && CSTAT(st_mtime));
545   memcpy(&last_stat, &sb, sizeof(sb));
546
547   if(reload) {
548     noit_hash_delete_all(&etc_hosts_cache, free, free);
549     while(NULL != (ent = gethostent())) {
550       int i = 0;
551       char *name = ent->h_name;
552       while(name) {
553         void *vnode;
554         static_host_node *node;
555         if(!noit_hash_retrieve(&etc_hosts_cache, name, strlen(name), &vnode)) {
556           vnode = node = calloc(1, sizeof(*node));
557           node->target = strdup(name);
558           noit_hash_store(&etc_hosts_cache, node->target, strlen(node->target), node);
559         }
560         node = vnode;
561  
562         if(ent->h_addrtype == AF_INET) {
563           node->has_ip4 = 1;
564           memcpy(&node->ip4, ent->h_addr_list[0], ent->h_length);
565         }
566         if(ent->h_addrtype == AF_INET6) {
567           node->has_ip6 = 1;
568           memcpy(&node->ip6, ent->h_addr_list[0], ent->h_length);
569         }
570        
571         name = ent->h_aliases[i++];
572       }
573     }
574     endhostent();
575     noitL(noit_error, "reloaded %d /etc/hosts targets\n", etc_hosts_cache.size);
576   }
577
578   eventer_add_in_s_us(noit_check_etc_hosts_cache_refresh, NULL, 1, 0);
579   return 0;
580 }
581
582 void noit_check_resolver_init() {
583   eventer_t e;
584   if(dns_init(NULL, 0) < 0)
585     noitL(noit_error, "dns initialization failed.\n");
586   dns_ctx = dns_new(NULL);
587   if(dns_init(dns_ctx, 0) != 0 ||
588      dns_open(dns_ctx) < 0) {
589     noitL(noit_error, "dns initialization failed.\n");
590   }
591   eventer_name_callback("dns_cache_callback", dns_cache_callback);
592   dns_set_tmcbck(dns_ctx, dns_cache_utm_fn, dns_ctx);
593   e = eventer_alloc();
594   e->mask = EVENTER_READ | EVENTER_EXCEPTION;
595   e->closure = dns_ctx;
596   e->callback = dns_cache_callback;
597   e->fd = dns_sock(dns_ctx);
598   eventer_add(e);
599
600   noit_skiplist_init(&nc_dns_cache);
601   noit_skiplist_set_compare(&nc_dns_cache, name_lookup, name_lookup_k);
602   noit_skiplist_add_index(&nc_dns_cache, refresh_idx, refresh_idx_k);
603   noit_check_resolver_loop(NULL, 0, NULL, NULL);
604   register_console_dns_cache_commands();
605
606   noit_hash_init(&etc_hosts_cache);
607   noit_check_etc_hosts_cache_refresh(NULL, 0, NULL, NULL);
608 }
Note: See TracBrowser for help on using the browser.