static int noit_lua_interpolate(lua_State *L) { noit_check_t *check; mtev_hash_table check_attrs_hash; char buff[8192]; if(lua_gettop(L) != 1) luaL_error(L, "wrong number of arguments"); check = lua_touserdata(L, lua_upvalueindex(1)); if(!lua_isstring(L,1) && !lua_istable(L,1)) { luaL_error(L, "noit.check.interpolate(<string|table>)"); } noit_check_make_attrs(check, &check_attrs_hash); if(lua_isstring(L,1)) { const char *ns = lua_tostring(L, 1); noit_check_interpolate(buff, sizeof(buff), ns, &check_attrs_hash, check->config); lua_pushstring(L, buff); } else { /* We have a table */ /* And we need a new table to return */ lua_createtable(L, 0, 0); /* push a blank key to prep for lua_next calls */ lua_pushnil(L); while(lua_next(L, -3)) { /* src table is -3 */ const char *key = lua_tostring(L, -2); if(lua_isstring(L, -1)) { const char *ns = lua_tostring(L,-1); noit_check_interpolate(buff, sizeof(buff), ns, &check_attrs_hash, check->config); lua_pop(L,1); lua_pushstring(L, buff); } lua_setfield(L, -3, key); /* tgt table is -3 */ } } mtev_hash_destroy(&check_attrs_hash, NULL, NULL); return 1; }
static int selfcheck_initiate(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { selfcheck_info_t *ci = check->closure; struct timeval __now; /* We cannot be running */ BAIL_ON_RUNNING_CHECK(check); check->flags |= NP_RUNNING; ci->self = self; ci->check = check; ci->timed_out = 1; noit_check_make_attrs(check, &ci->attrs); gettimeofday(&__now, NULL); memcpy(&check->last_fire_time, &__now, sizeof(__now)); /* Register a handler for the worker */ noit_check_run_full_asynch(check, selfcheck_log_size); return 0; }
static int postgres_initiate(noit_module_t *self, noit_check_t *check) { postgres_check_info_t *ci = check->closure; struct timeval __now; /* We cannot be running */ assert(!(check->flags & NP_RUNNING)); check->flags |= NP_RUNNING; ci->self = self; ci->check = check; ci->timed_out = 1; ci->rv = -1; noit_check_make_attrs(check, &ci->attrs); gettimeofday(&__now, NULL); memcpy(&check->last_fire_time, &__now, sizeof(__now)); /* Register a handler for the worker */ noit_check_run_full_asynch(check, postgres_drive_session); return 0; }
static int external_invoke(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { struct timeval when, p_int; external_closure_t *ecl; struct check_info *ci = (struct check_info *)check->closure; eventer_t newe; external_data_t *data; noit_hash_table check_attrs_hash = NOIT_HASH_EMPTY; int i, klen; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *name, *value; char interp_fmt[4096], interp_buff[4096]; data = noit_module_get_userdata(self); check->flags |= NP_RUNNING; noitL(data->nldeb, "external_invoke(%p,%s)\n", self, check->target); /* remove a timeout if we still have one -- we should unless someone * has set a lower timeout than the period. */ if(ci->timeout_event) { eventer_remove(ci->timeout_event); free(ci->timeout_event->closure); eventer_free(ci->timeout_event); ci->timeout_event = NULL; } check_info_clean(ci); gettimeofday(&when, NULL); memcpy(&check->last_fire_time, &when, sizeof(when)); /* Setup all our check bits */ ci->check_no = noit_atomic_inc64(&data->check_no_seq); ci->check = check; /* We might want to extract metrics */ if(noit_hash_retr_str(check->config, "output_extract", strlen("output_extract"), &value) != 0) { const char *error; int erroffset; ci->matcher = pcre_compile(value, 0, &error, &erroffset, NULL); if(!ci->matcher) { noitL(data->nlerr, "external pcre /%s/ failed @ %d: %s\n", value, erroffset, error); } } noit_check_make_attrs(check, &check_attrs_hash); /* Count the args */ i = 1; while(1) { char argname[10]; snprintf(argname, sizeof(argname), "arg%d", i); if(noit_hash_retr_str(check->config, argname, strlen(argname), &value) == 0) break; i++; } ci->argcnt = i + 1; /* path, arg0, (i-1 more args) */ ci->arglens = calloc(ci->argcnt, sizeof(*ci->arglens)); ci->args = calloc(ci->argcnt, sizeof(*ci->args)); /* Make the command */ if(noit_hash_retr_str(check->config, "command", strlen("command"), &value) == 0) { value = "/bin/true"; } ci->args[0] = strdup(value); ci->arglens[0] = strlen(ci->args[0]) + 1; i = 0; while(1) { char argname[10]; snprintf(argname, sizeof(argname), "arg%d", i); if(noit_hash_retr_str(check->config, argname, strlen(argname), &value) == 0) { if(i == 0) { /* if we don't have arg0, make it last element of path */ char *cp = ci->args[0] + strlen(ci->args[0]); while(cp > ci->args[0] && *(cp-1) != '/') cp--; value = cp; } else break; /* if we don't have argn, we're done */ } noit_check_interpolate(interp_buff, sizeof(interp_buff), value, &check_attrs_hash, check->config); ci->args[i+1] = strdup(interp_buff); ci->arglens[i+1] = strlen(ci->args[i+1]) + 1; i++; } /* Make the environment */ memset(&iter, 0, sizeof(iter)); ci->envcnt = 0; while(noit_hash_next_str(check->config, &iter, &name, &klen, &value)) if(!strncasecmp(name, "env_", 4)) ci->envcnt++; memset(&iter, 0, sizeof(iter)); ci->envlens = calloc(ci->envcnt, sizeof(*ci->envlens)); ci->envs = calloc(ci->envcnt, sizeof(*ci->envs)); ci->envcnt = 0; while(noit_hash_next_str(check->config, &iter, &name, &klen, &value)) if(!strncasecmp(name, "env_", 4)) { snprintf(interp_fmt, sizeof(interp_fmt), "%s=%s", name+4, value); noit_check_interpolate(interp_buff, sizeof(interp_buff), interp_fmt, &check_attrs_hash, check->config); ci->envs[ci->envcnt] = strdup(interp_buff); ci->envlens[ci->envcnt] = strlen(ci->envs[ci->envcnt]) + 1; ci->envcnt++; } noit_hash_destroy(&check_attrs_hash, NULL, NULL); noit_hash_store(&data->external_checks, (const char *)&ci->check_no, sizeof(ci->check_no), ci); /* Setup a timeout */ newe = eventer_alloc(); newe->mask = EVENTER_TIMER; gettimeofday(&when, NULL); p_int.tv_sec = check->timeout / 1000; p_int.tv_usec = (check->timeout % 1000) * 1000; add_timeval(when, p_int, &newe->whence); ecl = calloc(1, sizeof(*ecl)); ecl->self = self; ecl->check = check; newe->closure = ecl; newe->callback = external_timeout; eventer_add(newe); ci->timeout_event = newe; /* Setup push */ newe = eventer_alloc(); newe->mask = EVENTER_ASYNCH; add_timeval(when, p_int, &newe->whence); ecl = calloc(1, sizeof(*ecl)); ecl->self = self; ecl->check = check; newe->closure = ecl; newe->callback = external_enqueue; eventer_add(newe); 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; }