static int check_test_sweeper(eventer_t e, int mask, void *closure, struct timeval *now) { int left = 0; noit_skiplist_node *iter = NULL; sweeper_event = NULL; iter = noit_skiplist_getlist(&in_progress); while(iter) { struct check_test_closure *cl = iter->data; /* advance here, we might delete */ noit_skiplist_next(&in_progress,&iter); if(NOIT_CHECK_DISABLED(cl->check)) { if(NOIT_CHECK_SHOULD_RESOLVE(cl->check)) noit_check_resolve(cl->check); if(NOIT_CHECK_RESOLVED(cl->check)) { noit_module_t *m = noit_module_lookup(cl->check->module); cl->check->flags &= ~NP_DISABLED; if(NOIT_CHECK_SHOULD_RESOLVE(cl->check)) noitL(nldeb, "translated to %s\n", cl->check->target_ip); if(m) m->initiate_check(m, cl->check, 1, NULL); } left++; } else if(NOIT_CHECK_RUNNING(cl->check)) left++; else noit_skiplist_remove(&in_progress, cl->restc, (noit_freefunc_t)rest_test_check_result); } if(left) check_test_schedule_sweeper(); return 0; }
static void blank_update_v6(dns_cache_node *n) { int i; for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]); if(n->ip6) free(n->ip6); n->ip6 = NULL; n->ip6_cnt = 0; noit_skiplist_remove(&nc_dns_cache, n->target, NULL); n->last_updated = time(NULL); n->ttl = DEFAULT_FAILED_TTL; n->lookup_inflight_v6 = noit_false; noit_skiplist_insert(&nc_dns_cache, n); }
static int rest_test_check_err(noit_http_rest_closure_t *restc, int npats, char **pats) { noit_http_response *res = noit_http_session_response(restc->http_ctx); noit_skiplist_remove(&in_progress, restc, (noit_freefunc_t)rest_test_check_result); if(noit_http_response_complete(res) != noit_true) { noit_http_response_standard(restc->http_ctx, 500, "ERROR", "text/html"); noit_http_response_end(restc->http_ctx); } return 0; }
void noit_check_transient_remove_feed(noit_check_t *check, const char *feed) { if(!check->feeds) return; if(feed) { noitL(noit_debug, "check %s`%s @ %dms removing 1 of %d feeds: %s.\n", check->target, check->name, check->period, check->feeds->size, feed); noit_skiplist_remove(check->feeds, feed, free); } if(check->feeds->size == 0) { char uuid_str[UUID_STR_LEN + 1]; uuid_unparse_lower(check->checkid, uuid_str); noitL(noit_debug, "Unwatching %s@%d\n", uuid_str, check->period); noit_skiplist_remove(&watchlist, check, NULL); noit_skiplist_destroy(check->feeds, free); free(check->feeds); check->feeds = NULL; if(check->flags & NP_TRANSIENT) { noitL(noit_debug, "check %s`%s @ %dms has no more listeners.\n", check->target, check->name, check->period); check->flags |= NP_KILLED; } } }
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; } } }
int noit_poller_deschedule(uuid_t in) { void *vcheck; noit_check_t *checker; if(noit_hash_retrieve(&polls, (char *)in, UUID_SIZE, &vcheck) == 0) { return -1; } checker = (noit_check_t *)vcheck; checker->flags |= (NP_DISABLED|NP_KILLED); noit_skiplist_remove(&polls_by_name, checker, NULL); noit_hash_delete(&polls, (char *)in, UUID_SIZE, NULL, NULL); noit_poller_free_check(checker); return 0; }
static int noit_console_manip_dns_cache(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *dstate, void *closure) { int i; if(argc == 0) { nc_printf(ncct, "dns_cache what?\n"); return 0; } if(closure == NULL) { /* adding */ for(i=0;i<argc;i++) { dns_cache_node *n; if(NULL != (n = noit_skiplist_find(&nc_dns_cache, argv[i], NULL))) { nc_printf(ncct, " == Already in system ==\n"); nc_print_dns_cache_node(ncct, argv[i], n); } else { nc_printf(ncct, "%s submitted.\n", argv[i]); noit_check_resolver_remind(argv[i]); } } } else { for(i=0;i<argc;i++) { dns_cache_node *n; if(NULL != (n = noit_skiplist_find(&nc_dns_cache, argv[i], NULL))) { if(n->lookup_inflight_v4 || n->lookup_inflight_v6) nc_printf(ncct, "%s is currently resolving and cannot be removed.\n"); else { noit_skiplist_remove(&nc_dns_cache, argv[i], dns_cache_node_free); nc_printf(ncct, "%s removed.\n", argv[i]); } } else nc_printf(ncct, "%s not in system.\n", argv[i]); } } return 0; }
static void dns_cache_resolve(struct dns_ctx *ctx, void *result, void *data, enum dns_type rtype) { int i, ttl, acnt, r = dns_status(ctx); dns_cache_node *n = data; unsigned char idn[DNS_MAXDN], dn[DNS_MAXDN]; struct dns_parse p; struct dns_rr rr; unsigned nrr; char **answers; const unsigned char *pkt, *cur, *end; if(!result) goto blank; dns_dntodn(n->dn, idn, sizeof(idn)); pkt = result; end = pkt + r; cur = dns_payload(pkt); dns_getdn(pkt, &cur, end, dn, sizeof(dn)); dns_initparse(&p, NULL, pkt, cur, end); p.dnsp_qcls = 0; p.dnsp_qtyp = 0; nrr = 0; ttl = 0; while((r = dns_nextrr(&p, &rr)) > 0) { if (!dns_dnequal(idn, rr.dnsrr_dn)) continue; if (DNS_C_IN == rr.dnsrr_cls && rtype == rr.dnsrr_typ) ++nrr; else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) { if (dns_getdn(pkt, &rr.dnsrr_dptr, end, p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 || rr.dnsrr_dptr != rr.dnsrr_dend) { break; } else { if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl)) ttl = rr.dnsrr_ttl; dns_dntodn(p.dnsp_dnbuf, idn, sizeof(idn)); } } } if(!r && !nrr) goto blank; dns_rewind(&p, NULL); p.dnsp_qcls = DNS_C_IN; p.dnsp_qtyp = rtype; answers = calloc(nrr, sizeof(*answers)); acnt = 0; while(dns_nextrr(&p, &rr) && nrr < MAX_RR) { char buff[INET6_ADDRSTRLEN]; if (!dns_dnequal(idn, rr.dnsrr_dn)) continue; if (p.dnsp_rrl && !rr.dnsrr_dn[0] && rr.dnsrr_typ == DNS_T_OPT) continue; if (rtype == rr.dnsrr_typ) { if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl)) ttl = rr.dnsrr_ttl; switch(rr.dnsrr_typ) { case DNS_T_A: if(rr.dnsrr_dsz != 4) continue; inet_ntop(AF_INET, rr.dnsrr_dptr, buff, sizeof(buff)); answers[acnt++] = strdup(buff); break; case DNS_T_AAAA: if(rr.dnsrr_dsz != 16) continue; inet_ntop(AF_INET6, rr.dnsrr_dptr, buff, sizeof(buff)); answers[acnt++] = strdup(buff); break; default: break; } } } n->ttl = ttl; if(rtype == DNS_T_A) { for(i=0;i<n->ip4_cnt;i++) if(n->ip4[i]) free(n->ip4[i]); if(n->ip4) free(n->ip4); n->ip4_cnt = acnt; n->ip4 = answers; n->lookup_inflight_v4 = noit_false; } else if(rtype == DNS_T_AAAA) { for(i=0;i<n->ip6_cnt;i++) if(n->ip6[i]) free(n->ip6[i]); if(n->ip6) free(n->ip6); n->ip6_cnt = acnt; n->ip6 = answers; n->lookup_inflight_v6 = noit_false; } noit_skiplist_remove(&nc_dns_cache, n->target, NULL); n->last_updated = time(NULL); noit_skiplist_insert(&nc_dns_cache, n); noitL(noit_debug, "Resolved %s/%s -> %d records\n", n->target, (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")), acnt); if(result) free(result); return; blank: if(rtype == DNS_T_A) blank_update_v4(n); if(rtype == DNS_T_AAAA) blank_update_v6(n); noitL(noit_debug, "Resolved %s/%s -> blank\n", n->target, (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???"))); if(result) free(result); return; }
int noit_check_update(noit_check_t *new_check, const char *target, const char *name, const char *filterset, noit_hash_table *config, u_int32_t period, u_int32_t timeout, const char *oncheck, int flags) { int8_t family; int rv; int mask = NP_DISABLED | NP_UNCONFIG; union { struct in_addr addr4; struct in6_addr addr6; } a; family = AF_INET; rv = inet_pton(family, target, &a); if(rv != 1) { family = AF_INET6; rv = inet_pton(family, target, &a); if(rv != 1) { noitL(noit_stderr, "Cannot translate '%s' to IP\n", target); memset(&a, 0, sizeof(a)); flags |= (NP_UNCONFIG | NP_DISABLED); } } new_check->generation = __config_load_generation; new_check->target_family = family; memcpy(&new_check->target_addr, &a, sizeof(a)); if(new_check->target) free(new_check->target); new_check->target = strdup(target); if(new_check->name) free(new_check->name); new_check->name = name ? strdup(name): NULL; if(new_check->filterset) free(new_check->filterset); new_check->filterset = filterset ? strdup(filterset): NULL; if(config != NULL) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; if(new_check->config) noit_hash_delete_all(new_check->config, free, free); else new_check->config = calloc(1, sizeof(*new_check->config)); while(noit_hash_next(config, &iter, &k, &klen, &data)) { noit_hash_store(new_check->config, strdup(k), klen, strdup((char *)data)); } } if(new_check->oncheck) free(new_check->oncheck); new_check->oncheck = oncheck ? strdup(oncheck) : NULL; new_check->period = period; new_check->timeout = timeout; /* Unset what could be set.. then set what should be set */ new_check->flags = (new_check->flags & ~mask) | flags; if(!(new_check->flags & NP_TRANSIENT)) { /* This remove could fail -- no big deal */ noit_skiplist_remove(&polls_by_name, new_check, NULL); /* This insert could fail.. which means we have a conflict on * target`name. That should result in the check being disabled. */ if(!noit_skiplist_insert(&polls_by_name, new_check)) { noitL(noit_stderr, "Check %s`%s disabled due to naming conflict\n", new_check->target, new_check->name); new_check->flags |= NP_DISABLED; } } noit_check_log_check(new_check); return 0; }