static int dns_module_invoke_timeouts(eventer_t e, int mask, void *closure, struct timeval *now) { dns_ctx_handle_t *h = closure; dns_timeouts(h->ctx, 0, now->tv_sec); dns_module_dns_ctx_release(h); return 0; }
void noit_check_resolver_maintain() { time_t now; noit_skiplist *tlist; noit_skiplist_node *sn; now = time(NULL); sn = noit_skiplist_getlist(nc_dns_cache.index); tlist = sn->data; sn = noit_skiplist_getlist(tlist); while(sn) { dns_cache_node *n = sn->data; noit_skiplist_next(tlist, &sn); /* move forward */ /* remove if needed */ if(n->last_updated + n->ttl > now) break; if(n->last_needed + DEFAULT_PURGE_AGE < now && !(n->lookup_inflight_v4 || n->lookup_inflight_v6)) noit_skiplist_remove(&nc_dns_cache, n->target, dns_cache_node_free); else { int abs; if(!dns_ptodn(n->target, strlen(n->target), n->dn, sizeof(n->dn), &abs)) { blank_update(n); } else { if(!n->lookup_inflight_v4) { n->lookup_inflight_v4 = noit_true; if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_A, abs | DNS_NOSRCH, NULL, dns_cache_resolve_v4, n)) blank_update_v4(n); else dns_timeouts(dns_ctx, -1, now); } if(!n->lookup_inflight_v6) { n->lookup_inflight_v6 = noit_true; if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_AAAA, abs | DNS_NOSRCH, NULL, dns_cache_resolve_v6, n)) blank_update_v6(n); else dns_timeouts(dns_ctx, -1, now); } } noitL(noit_debug, "Firing lookup for '%s'\n", n->target); continue; } } }
static int noit_lua_dns_lookup(lua_State *L) { dns_lookup_ctx_t *dlc, **holder; const char *c, *query = "", *ctype = "IN", *rtype = "A"; char *ctype_up, *rtype_up, *d; void *vnv_pair; noit_lua_check_info_t *ci; ci = get_ci(L); assert(ci); holder = (dns_lookup_ctx_t **)lua_touserdata(L, lua_upvalueindex(1)); if(holder != lua_touserdata(L,1)) luaL_error(L, "Must be called as method\n"); dlc = *holder; if(lua_gettop(L) > 1) query = lua_tostring(L, 2); if(lua_gettop(L) > 2) rtype = lua_tostring(L, 3); if(lua_gettop(L) > 3) ctype = lua_tostring(L, 4); ctype_up = alloca(strlen(ctype)+1); for(d = ctype_up, c = ctype; *c; d++, c++) *d = toupper(*c); *d = '\0'; rtype_up = alloca(strlen(rtype)+1); for(d = rtype_up, c = rtype; *c; d++, c++) *d = toupper(*c); *d = '\0'; if(!noit_hash_retrieve(&dns_ctypes, ctype_up, strlen(ctype_up), &vnv_pair)) dlc->error = strdup("bad class"); else dlc->query_ctype = ((struct dns_nameval *)vnv_pair)->val; if(!noit_hash_retrieve(&dns_rtypes, rtype_up, strlen(rtype_up), &vnv_pair)) dlc->error = strdup("bad rr type"); else dlc->query_rtype = ((struct dns_nameval *)vnv_pair)->val; dlc->active = 1; noit_atomic_inc32(&dlc->refcnt); if(!dlc->error) { int abs; if(!dns_ptodn(query, strlen(query), dlc->dn, sizeof(dlc->dn), &abs) || !dns_submit_dn(dlc->h->ctx, dlc->dn, dlc->query_ctype, dlc->query_rtype, abs | DNS_NOSRCH, NULL, dns_cb, dlc)) { dlc->error = strdup("submission error"); noit_atomic_dec32(&dlc->refcnt); } else { struct timeval now; gettimeofday(&now, NULL); dns_timeouts(dlc->h->ctx, -1, now.tv_sec); } } if(dlc->error) { dlc->active = 0; luaL_error(L, "dns: %s\n", dlc->error); } return noit_lua_yield(ci, 0); }
/* * DNS timeout callback */ static void resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) { struct dns_ctx *ctx = (struct dns_ctx *)w->data; if (revents & EV_TIMER) { dns_timeouts(ctx, 30, ev_now(loop)); } }
/* * Wrapper for client callback we provide to udns */ static void dns_query_cb(struct dns_ctx *ctx, struct dns_rr_a4 *result, void *data) { struct ResolvQuery *cb_data = (struct ResolvQuery *)data; struct Address *address = NULL; if (result == NULL) { info("resolv: %s\n", dns_strerror(dns_status(ctx))); } else if (result->dnsa4_nrr > 0) { struct sockaddr_in sa = { .sin_family = AF_INET, .sin_port = 0, .sin_addr = result->dnsa4_addr[0], }; address = new_address_sa((struct sockaddr *)&sa, sizeof(sa)); if (address == NULL) err("Failed to allocate memory for DNS query result address"); } cb_data->client_cb(address, cb_data->client_cb_data); cb_data->client_free_cb(cb_data->client_cb_data); free(cb_data); free(result); free(address); } /* * DNS timeout callback */ static void resolv_timeout_cb(struct ev_loop *loop, struct ev_timer *w, int revents) { struct dns_ctx *ctx = (struct dns_ctx *)w->data; dns_timeouts(ctx, 30, ev_now(loop)); } /* * Callback to setup DNS timeout callback */ static void dns_timer_setup_cb(struct dns_ctx *ctx, int timeout, void *data) { struct ev_loop *loop = (struct ev_loop *)data; if (ev_is_active(&resolv_timeout_watcher)) ev_timer_stop(loop, &resolv_timeout_watcher); if (ctx != NULL && timeout >= 0) { ev_timer_set(&resolv_timeout_watcher, timeout, 0.0); ev_timer_start(loop, &resolv_timeout_watcher); } }
static void dns_timeout_cb (EV_P_ ev_timer *w, int revents) { ev_now_update(EV_A); ev_tstamp now = ev_now(EV_A ); int next = dns_timeouts(NULL, -1, now); if (next > 0) { w->repeat = next; ev_timer_again (EV_A_ w); } else { w->repeat = 1; ev_timer_again (EV_A_ w); } }
/*@null@*/ static PyObject* Resolver_timeouts (Resolver *self, PyObject *args) { time_t now = 0; int wait = 0, maxwait = 0; if (!PyArg_ParseTuple(args, "i|l", &maxwait, &now)) { PyErr_SetString(PyExc_TypeError, "Resolver.timeouts(maxwait, now=0) takes 2 int arguments: maxwait and current timestamp."); return NULL; } wait = dns_timeouts(self->ctx, maxwait, now); return Py_BuildValue("i", wait); }
static void waitdns(struct ipcheck *ipc) { struct timeval tv; fd_set fds; int c; int fd = dns_sock(NULL); time_t now = 0; FD_ZERO(&fds); while((c = dns_timeouts(NULL, -1, now)) > 0) { FD_SET(fd, &fds); tv.tv_sec = c; tv.tv_usec = 0; c = select(fd+1, &fds, NULL, NULL, &tv); now = time(NULL); if (c > 0) dns_ioevent(NULL, now); if (stopfirst && ipc->listed) break; } }
void ape_gethostbyname(char *name, void (*callback)(char *, void *, acetables *), void *data, acetables *g_ape) { struct in_addr addr; struct query *q; unsigned char dn[DNS_MAXDN]; int abs = 0; enum dns_type l_qtyp = 0; if (dns_pton(AF_INET, name, &addr) > 0) { /* We have an IP */ callback(xstrdup(name), data, g_ape); return; } else if (!dns_ptodn(name, strlen(name), dn, sizeof(dn), &abs)) { /* We have an invalid domain name */ return; } else { l_qtyp = DNS_T_A; } q = query_new(name, dn, l_qtyp); q->data = data; q->callback = callback; q->g_ape = g_ape; if (abs) { abs = DNS_NOSRCH; } if (!dns_submit_dn(NULL, dn, qcls, l_qtyp, abs, 0, dnscb, q)) { query_free(q); return; } dns_timeouts(NULL, -1, 0); }
static int dns_invoke_timeouts(eventer_t e, int mask, void *closure, struct timeval *now) { struct dns_ctx *ctx = closure; dns_timeouts(ctx, 0, now->tv_sec); return 0; }
static int dns_check_send(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { void *vnv_pair = NULL; struct dns_nameval *nv_pair; eventer_t newe; struct timeval p_int, now; struct dns_check_info *ci = check->closure; const char *config_val; const char *rtype = NULL; const char *nameserver = NULL; int port = 0; const char *port_str = NULL; const char *want_sort = NULL; const char *ctype = "IN"; const char *query = NULL; char interpolated_nameserver[1024]; char interpolated_query[1024]; noit_hash_table check_attrs_hash = NOIT_HASH_EMPTY; BAIL_ON_RUNNING_CHECK(check); gettimeofday(&now, NULL); memcpy(&check->last_fire_time, &now, sizeof(now)); ci->current.state = NP_BAD; ci->current.available = NP_UNAVAILABLE; ci->timed_out = 1; ci->nrr = 0; ci->sort = 1; if(!strcmp(check->name, "in-addr.arpa") || (strlen(check->name) >= sizeof("::in-addr.arpa") - 1 && !strcmp(check->name + strlen(check->name) - sizeof("::in-addr.arpa") + 1, "::in-addr.arpa"))) { /* in-addr.arpa defaults: * nameserver to NULL * rtype to PTR * query to %[:inaddrarpa:target] */ nameserver = NULL; rtype = "PTR"; query = "%[:inaddrarpa:target_ip]"; } else { nameserver = "%[target_ip]"; rtype = "A"; query = "%[name]"; } if(noit_hash_retr_str(check->config, "port", strlen("port"), &port_str)) { port = atoi(port_str); } #define CONFIG_OVERRIDE(a) \ if(noit_hash_retr_str(check->config, #a, strlen(#a), \ &config_val) && \ strlen(config_val) > 0) \ a = config_val CONFIG_OVERRIDE(ctype); CONFIG_OVERRIDE(nameserver); CONFIG_OVERRIDE(rtype); CONFIG_OVERRIDE(query); CONFIG_OVERRIDE(want_sort); if(nameserver && !strcmp(nameserver, "default")) nameserver = NULL; if(want_sort && strcasecmp(want_sort, "on") && strcasecmp(want_sort, "true")) ci->sort = 0; noit_check_make_attrs(check, &check_attrs_hash); if(nameserver) { noit_check_interpolate(interpolated_nameserver, sizeof(interpolated_nameserver), nameserver, &check_attrs_hash, check->config); nameserver = interpolated_nameserver; } if(query) { noit_check_interpolate(interpolated_query, sizeof(interpolated_query), query, &check_attrs_hash, check->config); query = interpolated_query; } noit_hash_destroy(&check_attrs_hash, NULL, NULL); check->flags |= NP_RUNNING; noitL(nldeb, "dns_check_send(%p,%s,%s,%s,%s,%s)\n", self, check->target, nameserver ? nameserver : "default", query ? query : "null", ctype, rtype); __activate_ci(ci); /* If this ci has a handle and it isn't the one we need, * we should release it */ if(ci->h && ((ci->h->ns == NULL && nameserver != NULL) || (ci->h->ns != NULL && nameserver == NULL) || (ci->h->ns && strcmp(ci->h->ns, nameserver)))) { dns_ctx_release(ci->h); ci->h = NULL; } /* use the cached one, unless we don't have one */ if(!ci->h) ci->h = dns_ctx_alloc(nameserver, port); if(!ci->h) ci->error = strdup("bad nameserver"); /* Lookup out class */ if(!noit_hash_retrieve(&dns_ctypes, ctype, strlen(ctype), &vnv_pair)) { if(ci->error) free(ci->error); ci->error = strdup("bad class"); } else { nv_pair = (struct dns_nameval *)vnv_pair; ci->query_ctype = nv_pair->val; } /* Lookup out rr type */ if(!noit_hash_retrieve(&dns_rtypes, rtype, strlen(rtype), &vnv_pair)) { if(ci->error) free(ci->error); ci->error = strdup("bad rr type"); } else { nv_pair = (struct dns_nameval *)vnv_pair; ci->query_rtype = nv_pair->val; } if(!ci->error) { /* Submit the query */ int abs; if(!dns_ptodn(query, strlen(query), ci->dn, sizeof(ci->dn), &abs) || !dns_submit_dn(ci->h->ctx, ci->dn, ci->query_ctype, ci->query_rtype, abs | DNS_NOSRCH, NULL, dns_cb, ci)) { ci->error = strdup("submission error"); } else { dns_timeouts(ci->h->ctx, -1, now.tv_sec); } } /* we could have completed by now... if so, we've nothing to do */ if(!__isactive_ci(ci)) return 0; if(ci->error) { /* Errors here are easy, fail and avoid scheduling a timeout */ ci->check->flags &= ~NP_RUNNING; dns_check_log_results(ci); __deactivate_ci(ci); return 0; } newe = eventer_alloc(); newe->mask = EVENTER_TIMER; gettimeofday(&now, NULL); p_int.tv_sec = check->timeout / 1000; p_int.tv_usec = (check->timeout % 1000) * 1000; add_timeval(now, p_int, &newe->whence); newe->closure = ci; newe->callback = dns_check_timeout; ci->timeout_event = newe; eventer_add(newe); return 0; }
void noit_check_resolver_maintain() { time_t now; mtev_skiplist *tlist; mtev_skiplist_node *sn; now = time(NULL); sn = mtev_skiplist_getlist(nc_dns_cache.index); assert(sn); tlist = sn->data; assert(tlist); sn = mtev_skiplist_getlist(tlist); while(sn) { dns_cache_node *n = sn->data; mtev_skiplist_next(tlist, &sn); /* move forward */ /* remove if needed */ if(n->last_updated + n->ttl > now) break; if(n->last_needed + DEFAULT_PURGE_AGE < now && !(n->lookup_inflight_v4 || n->lookup_inflight_v6)) mtev_skiplist_remove(&nc_dns_cache, n->target, dns_cache_node_free); else { int abs; if(!dns_ptodn(n->target, strlen(n->target), n->dn, sizeof(n->dn), &abs)) { blank_update(n); } else { if(!n->lookup_inflight_v4) { n->lookup_inflight_v4 = mtev_true; if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_A, abs | dns_search_flag, NULL, dns_cache_resolve_v4, n)) blank_update_v4(n); else dns_timeouts(dns_ctx, -1, now); } if(!n->lookup_inflight_v6) { n->lookup_inflight_v6 = mtev_true; if(!dns_submit_dn(dns_ctx, n->dn, DNS_C_IN, DNS_T_AAAA, abs | dns_search_flag, NULL, dns_cache_resolve_v6, n)) blank_update_v6(n); else dns_timeouts(dns_ctx, -1, now); } } mtevL(noit_debug, "Firing lookup for '%s'\n", n->target); continue; } } /* If we have a cache implementation */ if(noit_resolver_cache_store_hook_exists()) { /* And that implementation is interested in getting a dump... */ if(noit_resolver_cache_store_hook_invoke(NULL, NULL, 0) == MTEV_HOOK_CONTINUE) { mtev_skiplist_node *sn; /* dump it all */ DCLOCK(); for(sn = mtev_skiplist_getlist(&nc_dns_cache); sn; mtev_skiplist_next(&nc_dns_cache, &sn)) { int sbuffsize; char sbuff[1024]; dns_cache_node *n = (dns_cache_node *)sn->data; sbuffsize = dns_cache_node_serialize(sbuff, sizeof(sbuff), n); if(sbuffsize > 0) noit_resolver_cache_store_hook_invoke(n->target, sbuff, sbuffsize); } DCUNLOCK(); } } }
static int noit_lua_dns_timeouts(eventer_t e, int mask, void *closure, struct timeval *now) { dns_ctx_handle_t *h = closure; dns_timeouts(h->ctx, 0, now->tv_sec); return 0; }
static void ape_dns_timeout(void *params, int *last) { dns_timeouts(NULL, -1, 0); }