Esempio n. 1
0
int
resolv_init(struct ev_loop *loop, char **nameservers, int nameserver_num, int ipv6first)
{
    if (ipv6first)
        resolv_mode = MODE_IPV6_FIRST;
    else
        resolv_mode = MODE_IPV4_FIRST;

    struct dns_ctx *ctx = &dns_defctx;
    if (nameservers == NULL) {
        /* Nameservers not specified, use system resolver config */
        dns_init(ctx, 0);
    } else {
        dns_reset(ctx);

        for (int i = 0; i < nameserver_num; i++) {
            char *server = nameservers[i];
            dns_add_serv(ctx, server);
        }
    }

    int sockfd = dns_open(ctx);
    if (sockfd < 0) {
        FATAL("Failed to open DNS resolver socket");
    }

    if (nameserver_num == 1 && nameservers != NULL) {
        if (strncmp("127.0.0.1", nameservers[0], 9) == 0
            || strncmp("::1", nameservers[0], 3) == 0) {
            if (verbose) {
                LOGI("bind UDP resolver to %s", nameservers[0]);
            }
            if (bind_to_address(sockfd, nameservers[0]) == -1)
                ERROR("bind_to_address");
        }
    }

#ifdef __MINGW32__
    setnonblocking(sockfd);
#else
    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
#endif

    ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ);
    resolv_io_watcher.data = ctx;

    ev_io_start(loop, &resolv_io_watcher);

    ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0);
    resolv_timeout_watcher.data = ctx;

    dns_set_tmcbck(ctx, dns_timer_setup_cb, loop);

    return sockfd;
}
Esempio n. 2
0
static dns_ctx_handle_t *dns_ctx_alloc(const char *ns, int port) {
  void *vh;
  dns_ctx_handle_t *h = NULL;
  pthread_mutex_lock(&dns_ctx_store_lock);
  if(ns == NULL && default_ctx_handle != NULL) {
    /* special case -- default context */
    h = default_ctx_handle;
    noit_atomic_inc32(&h->refcnt);
    goto bail;
  }
  if(ns &&
     noit_hash_retrieve(&dns_ctx_store, ns, strlen(ns), &vh)) {
    h = (dns_ctx_handle_t *)vh;
    noit_atomic_inc32(&h->refcnt);
  }
  else {
    int failed = 0;
    h = calloc(1, sizeof(*h));
    h->ns = ns ? strdup(ns) : NULL;
    h->ctx = dns_new(NULL);
    if(dns_init(h->ctx, 0) != 0) failed++;
    if(ns) {
      if(dns_add_serv(h->ctx, NULL) < 0) failed++;
      if(dns_add_serv(h->ctx, ns) < 0) failed++;
    }
    if(port && port != DNS_PORT) {
      dns_set_opt(h->ctx, DNS_OPT_PORT, port);
    }
    if(dns_open(h->ctx) < 0) failed++;
    if(failed) {
      noitL(nlerr, "dns_open failed\n");
      free(h->ns);
      free(h);
      h = NULL;
      goto bail;
    }
    dns_set_tmcbck(h->ctx, eventer_dns_utm_fn, h);
    h->e = eventer_alloc();
    h->e->mask = EVENTER_READ | EVENTER_EXCEPTION;
    h->e->closure = h;
    h->e->callback = dns_eventer_callback;
    h->e->fd = dns_sock(h->ctx);
    eventer_add(h->e);
    h->refcnt = 1;
    if(!ns)
      default_ctx_handle = h;
    else
      noit_hash_store(&dns_ctx_store, h->ns, strlen(h->ns), h);
  }
 bail:
  pthread_mutex_unlock(&dns_ctx_store_lock);
  return h;
}
Esempio n. 3
0
int
resolv_init(struct ev_loop *loop) {
    struct dns_ctx *ctx = &dns_defctx;
    dns_init(ctx, 1);

    int sockfd = dns_sock(ctx);

    int flags = fcntl(sockfd, F_GETFL, 0);
    fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

    ev_io_init(&resolv_io_watcher, resolv_sock_cb, sockfd, EV_READ);
    resolv_io_watcher.data = ctx;

    ev_io_start(loop, &resolv_io_watcher);


    ev_timer_init(&resolv_timeout_watcher, resolv_timeout_cb, 0.0, 0.0);
    resolv_timeout_watcher.data = ctx;

    dns_set_tmcbck(ctx, dns_timer_setup_cb, loop);

    return sockfd;
}
void noit_check_resolver_init() {
  eventer_t e;
  if(dns_init(NULL, 0) < 0)
    noitL(noit_error, "dns initialization failed.\n");
  dns_ctx = dns_new(NULL);
  if(dns_init(dns_ctx, 0) != 0 ||
     dns_open(dns_ctx) < 0) {
    noitL(noit_error, "dns initialization failed.\n");
  }
  eventer_name_callback("dns_cache_callback", dns_cache_callback);
  dns_set_tmcbck(dns_ctx, dns_cache_utm_fn, dns_ctx);
  e = eventer_alloc();
  e->mask = EVENTER_READ | EVENTER_EXCEPTION;
  e->closure = dns_ctx;
  e->callback = dns_cache_callback;
  e->fd = dns_sock(dns_ctx);
  eventer_add(e);

  noit_skiplist_init(&nc_dns_cache);
  noit_skiplist_set_compare(&nc_dns_cache, name_lookup, name_lookup_k);
  noit_skiplist_add_index(&nc_dns_cache, refresh_idx, refresh_idx_k);
  noit_check_resolver_loop(NULL, 0, NULL, NULL);
  register_console_dns_cache_commands();
}
Esempio n. 5
0
void noit_check_resolver_init() {
  int cnt;
  mtev_conf_section_t *servers, *searchdomains;
  eventer_t e;
  if(dns_init(NULL, 0) < 0)
    mtevL(noit_error, "dns initialization failed.\n");
  dns_ctx = dns_new(NULL);
  if(dns_init(dns_ctx, 0) != 0) {
    mtevL(noit_error, "dns initialization failed.\n");
    exit(-1);
  }

  /* Optional servers */
  servers = mtev_conf_get_sections(NULL, "//resolver//server", &cnt);
  if(cnt) {
    int i;
    char server[128];
    dns_add_serv(dns_ctx, NULL); /* reset */
    for(i=0;i<cnt;i++) {
      if(mtev_conf_get_stringbuf(servers[i], "self::node()",
                                 server, sizeof(server))) {
        if(dns_add_serv(dns_ctx, server) < 0) {
          mtevL(noit_error, "Failed adding DNS server: %s\n", server);
        }
      }
    }
    free(servers);
  }
  searchdomains = mtev_conf_get_sections(NULL, "//resolver//search", &cnt);
  if(cnt) {
    int i;
    char search[128];
    dns_add_srch(dns_ctx, NULL); /* reset */
    for(i=0;i<cnt;i++) {
      if(mtev_conf_get_stringbuf(searchdomains[i], "self::node()",
                                 search, sizeof(search))) {
        if(dns_add_srch(dns_ctx, search) < 0) {
          mtevL(noit_error, "Failed adding DNS search path: %s\n", search);
        }
        else if(dns_search_flag) dns_search_flag = 0; /* enable search */
      }
    }
    free(searchdomains);
  }

  if(mtev_conf_get_int(NULL, "//resolver/@ndots", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_NDOTS, cnt);

  if(mtev_conf_get_int(NULL, "//resolver/@ntries", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_NTRIES, cnt);

  if(mtev_conf_get_int(NULL, "//resolver/@timeout", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_TIMEOUT, cnt);

  if(dns_open(dns_ctx) < 0) {
    mtevL(noit_error, "dns open failed.\n");
    exit(-1);
  }
  eventer_name_callback("dns_cache_callback", dns_cache_callback);
  dns_set_tmcbck(dns_ctx, dns_cache_utm_fn, dns_ctx);
  e = eventer_alloc();
  e->mask = EVENTER_READ | EVENTER_EXCEPTION;
  e->closure = dns_ctx;
  e->callback = dns_cache_callback;
  e->fd = dns_sock(dns_ctx);
  eventer_add(e);

  mtev_skiplist_init(&nc_dns_cache);
  mtev_skiplist_set_compare(&nc_dns_cache, name_lookup, name_lookup_k);
  mtev_skiplist_add_index(&nc_dns_cache, refresh_idx, refresh_idx_k);

  /* maybe load it from cache */
  if(noit_resolver_cache_load_hook_exists()) {
    struct timeval now;
    char *key;
    void *data;
    int len;
    gettimeofday(&now, NULL);
    while(noit_resolver_cache_load_hook_invoke(&key, &data, &len) == MTEV_HOOK_CONTINUE) {
      dns_cache_node *n;
      n = calloc(1, sizeof(*n));
      if(dns_cache_node_deserialize(n, data, len) >= 0) {
        n->target = strdup(key);
        /* if the TTL indicates that it will expire in less than 60 seconds
         * (including stuff that should have already expired), then fudge
         * the last_updated time to make it expire some random time within
         * the next 60 seconds.
         */
        if(n->last_needed > now.tv_sec || n->last_updated > now.tv_sec)
          break; /* impossible */

        n->last_needed = now.tv_sec;
        if(n->last_updated + n->ttl < now.tv_sec + 60) {
          int fudge = MIN(60, n->ttl) + 1;
          n->last_updated = now.tv_sec - n->ttl + (lrand48() % fudge);
        }
        DCLOCK();
        mtev_skiplist_insert(&nc_dns_cache, n);
        DCUNLOCK();
        n = NULL;
      }
      else {
        mtevL(noit_error, "Failed to deserialize resolver cache record.\n");
      }
      if(n) dns_cache_node_free(n);
      if(key) free(key);
      if(data) free(data);
    }
  }

  noit_check_resolver_loop(NULL, 0, NULL, NULL);
  register_console_dns_cache_commands();

  mtev_hash_init(&etc_hosts_cache);
  noit_check_etc_hosts_cache_refresh(NULL, 0, NULL, NULL);
}
Esempio n. 6
0
static dns_ctx_handle_t *dns_module_dns_ctx_alloc(noit_module_t *self, const char *ns, int port) {
  void *vh;
  char *hk = NULL;
  dns_mod_config_t *conf = noit_module_get_userdata(self);
  int randkey = random() % conf->contexts;
  dns_ctx_handle_t *h = NULL;
  if(ns && *ns == '\0') ns = NULL;
  pthread_mutex_lock(&dns_ctx_store_lock);
  if(ns == NULL && default_ctx_handle != NULL) {
    /* special case -- default context */
    h = default_ctx_handle;
    dns_module_dns_ctx_acquire(h);
    goto bail;
  }

  if (ns != NULL) {
    int len = snprintf(NULL, 0, "%s:%d:%d", ns, port, randkey); 
    hk = (char *)malloc(len+1);
    snprintf(hk, len+1, "%s:%d:%d", ns, port, randkey);
  }

  if(ns &&
     noit_hash_retrieve(&dns_ctx_store, hk, strlen(hk), &vh)) {
    h = (dns_ctx_handle_t *)vh;
    dns_module_dns_ctx_acquire(h);
    free(hk);
  }
  else {
    int failed = 0;
    h = calloc(1, sizeof(*h));
    h->ns = ns ? strdup(ns) : NULL;
    h->ctx = dns_new(NULL);
    if(dns_init(h->ctx, 0) != 0) {
      noitL(nlerr, "dns_init failed\n");
      failed++;
    }
    dns_set_dbgfn(h->ctx, dns_debug_wrap);
    if(ns) {
      if(dns_add_serv(h->ctx, NULL) < 0) {
        noitL(nlerr, "dns_add_serv(NULL) failed\n");
        failed++;
      }
      if(dns_add_serv(h->ctx, ns) < 0) {
        noitL(nlerr, "dns_add_serv(%s) failed\n", ns);
        failed++;
      }
    }
    if(port && port != DNS_PORT) {
      dns_set_opt(h->ctx, DNS_OPT_PORT, port);
    }
    if(dns_open(h->ctx) < 0) {
      noitL(nlerr, "dns_open failed\n");
      failed++;
    }
    if(failed) {
      free(h->ns);
      dns_free(h->ctx);
      free(h);
      free(hk);
      h = NULL;
      goto bail;
    }
    h->hkey = hk;
    dns_set_tmcbck(h->ctx, dns_module_eventer_dns_utm_fn, h);
    h->e = eventer_alloc();
    h->e->mask = EVENTER_READ | EVENTER_EXCEPTION;
    h->e->closure = h;
    h->e->callback = dns_module_eventer_callback;
    h->e->fd = dns_sock(h->ctx);
    eventer_add(h->e);
    h->refcnt = 1;
    if(!ns)
      default_ctx_handle = h;
    else
      noit_hash_store(&dns_ctx_store, h->hkey, strlen(h->hkey), h);
  }
 bail:
  pthread_mutex_unlock(&dns_ctx_store_lock);
  return h;
}