root/src/noit_check_resolver.c

Revision 25acde3fcc026a55eae0384c03b1addfda1c9cb6, 18.2 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 3 weeks ago)

change some boot error message to debug messages

  • 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_debug, "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.