void mtev_skiplist_set_compare(mtev_skiplist *sl, mtev_skiplist_comparator_t comp, mtev_skiplist_comparator_t compk) { if(sl->compare && sl->comparek) { mtev_skiplist_add_index(sl, comp, compk); } else { sl->compare = comp; sl->comparek = compk; } }
int external_child(external_data_t *data) { in_fd = data->pipe_n2e[0]; out_fd = data->pipe_e2n[1]; nlerr = data->nlerr; nldeb = data->nldeb; /* switch to / */ if(chdir("/") != 0) { mtevL(noit_error, "Failed chdir(\"/\"): %s\n", strerror(errno)); return -1; } mtev_skiplist_init(&active_procs); mtev_skiplist_set_compare(&active_procs, __proc_state_check_no, __proc_state_check_no_key); mtev_skiplist_add_index(&active_procs, __proc_state_pid, __proc_state_pid_key); mtev_skiplist_init(&done_procs); mtev_skiplist_set_compare(&done_procs, __proc_state_check_no, __proc_state_check_no_key); while(1) { struct pollfd pfd; struct proc_state *proc_state; int64_t check_no; int16_t argcnt, *arglens, envcnt, *envlens; int i; sig_noop(SIGCHLD); /* We poll here so that we can be interrupted by the SIGCHLD */ pfd.fd = in_fd; pfd.events = POLLIN; while(poll(&pfd, 1, -1) == -1 && errno == EINTR) finish_procs(); assert_read(in_fd, &check_no, sizeof(check_no)); assert_read(in_fd, &argcnt, sizeof(argcnt)); if(argcnt == 0) { /* cancellation */ fetch_and_kill_by_check(check_no); continue; } assert(argcnt > 1); proc_state = calloc(1, sizeof(*proc_state)); proc_state->stdout_fd = -1; proc_state->stderr_fd = -1; proc_state->check_no = check_no; /* read in the argument lengths */ arglens = calloc(argcnt, sizeof(*arglens)); assert_read(in_fd, arglens, argcnt * sizeof(*arglens)); /* first string is the path, second is the first argv[0] */ /* we need to allocate argcnt + 1 (NULL), but the first is path */ proc_state->argv = malloc(argcnt * sizeof(*proc_state->argv)); /* read each string, first in path, second into argv[0], ... */ /* arglens[i] comes from the parent, so we should trust it */ /* coverity[tainted_data] */ proc_state->path = malloc(arglens[0]); assert_read(in_fd, proc_state->path, arglens[0]); for(i=0; i<argcnt-1; i++) { proc_state->argv[i] = malloc(arglens[i+1]); assert_read(in_fd, proc_state->argv[i], arglens[i+1]); } proc_state->argv[i] = NULL; free(arglens); /* similar thing with envp, but no path trickery */ assert_read(in_fd, &envcnt, sizeof(envcnt)); envlens = calloc(envcnt, sizeof(*envlens)); assert_read(in_fd, envlens, envcnt * sizeof(*envlens)); proc_state->envp = malloc((envcnt+1) * sizeof(*proc_state->envp)); for(i=0; i<envcnt; i++) { proc_state->envp[i] = malloc(envlens[i]); assert_read(in_fd, proc_state->envp[i], envlens[i]); } proc_state->envp[i] = NULL; free(envlens); /* All set, this just needs to be run */ external_proc_spawn(proc_state); finish_procs(); } }
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); }