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); }
int noit_control_dispatch(eventer_t e, int mask, void *closure, struct timeval *now) { u_int32_t cmd; int len = 0, callmask = mask; void *vdelegation_table; noit_hash_table *delegation_table = NULL; acceptor_closure_t *ac = closure; assert(ac->rlen >= 0); while(len >= 0 && ac->rlen < sizeof(cmd)) { len = e->opset->read(e->fd, ((char *)&cmd) + ac->rlen, sizeof(cmd) - ac->rlen, &mask, e); if(len == -1 && errno == EAGAIN) return EVENTER_READ | EVENTER_EXCEPTION; if(len > 0) ac->rlen += len; } assert(ac->rlen >= 0 && ac->rlen <= sizeof(cmd)); if(callmask & EVENTER_EXCEPTION || ac->rlen != sizeof(cmd)) { int newmask; socket_error: /* Exceptions cause us to simply snip the connection */ eventer_remove_fd(e->fd); e->opset->close(e->fd, &newmask, e); acceptor_closure_free(ac); return 0; } ac->cmd = ntohl(cmd); /* Lookup cmd and dispatch */ if(noit_hash_retrieve(&listener_commands, (char *)&ac->dispatch, sizeof(ac->dispatch), (void **)&vdelegation_table)) { void *vfunc; delegation_table = (noit_hash_table *)vdelegation_table; if(noit_hash_retrieve(delegation_table, (char *)&ac->cmd, sizeof(ac->cmd), &vfunc)) { e->callback = *((eventer_func_t *)vfunc); return e->callback(e, callmask, closure, now); } else { const char *event_name; noitL(noit_error, "listener (%s %p) has no command: 0x%08x\n", (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???", delegation_table, cmd); } } else { const char *event_name; noitL(noit_error, "No delegation table for listener (%s %p)\n", (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???", delegation_table); } goto socket_error; }
noit_check_t * noit_check_clone(uuid_t in) { noit_check_t *checker, *new_check; void *vcheck; if(noit_hash_retrieve(&polls, (char *)in, UUID_SIZE, &vcheck) == 0) { return NULL; } checker = (noit_check_t *)vcheck; if(checker->oncheck) { return NULL; } new_check = calloc(1, sizeof(*new_check)); memcpy(new_check, checker, sizeof(*new_check)); new_check->target = strdup(new_check->target); new_check->module = strdup(new_check->module); new_check->name = strdup(new_check->name); new_check->filterset = strdup(new_check->filterset); new_check->flags = 0; new_check->fire_event = NULL; memset(&new_check->last_fire_time, 0, sizeof(new_check->last_fire_time)); memset(&new_check->stats, 0, sizeof(new_check->stats)); new_check->closure = NULL; new_check->config = calloc(1, sizeof(*new_check->config)); noit_hash_merge_as_dict(new_check->config, checker->config); return new_check; }
void noit_control_dispatch_delegate(eventer_func_t listener_dispatch, u_int32_t cmd, eventer_func_t delegate_dispatch) { u_int32_t *cmd_copy; eventer_func_t *handler_copy; void *vdelegation_table; noit_hash_table *delegation_table; if(!noit_hash_retrieve(&listener_commands, (char *)&listener_dispatch, sizeof(listener_dispatch), &vdelegation_table)) { delegation_table = calloc(1, sizeof(*delegation_table)); handler_copy = malloc(sizeof(*handler_copy)); *handler_copy = listener_dispatch; noit_hash_store(&listener_commands, (char *)handler_copy, sizeof(*handler_copy), delegation_table); } else delegation_table = (noit_hash_table *)vdelegation_table; cmd_copy = malloc(sizeof(*cmd_copy)); *cmd_copy = cmd; handler_copy = malloc(sizeof(*handler_copy)); *handler_copy = delegate_dispatch; noit_hash_replace(delegation_table, (char *)cmd_copy, sizeof(*cmd_copy), handler_copy, free, free); }
noit_boolean noit_apply_filterset(const char *filterset, noit_check_t *check, metric_t *metric) { /* We pass in filterset here just in case someone wants to apply * a filterset other than check->filterset.. You never know. */ void *vfs; if(!filterset) return noit_true; /* No filter */ if(!filtersets) return noit_false; /* Couldn't possibly match */ LOCKFS(); if(noit_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) { filterset_t *fs = (filterset_t *)vfs; filterrule_t *r; noit_atomic_inc32(&fs->ref_cnt); UNLOCKFS(); #define MATCHES(rname, value) noit_apply_filterrule(r->rname, r->rname##_e, value) for(r = fs->rules; r; r = r->next) { if(MATCHES(target, check->target) && MATCHES(module, check->module) && MATCHES(name, check->name) && MATCHES(metric, metric->metric_name)) return (r->type == NOIT_FILTER_ACCEPT) ? noit_true : noit_false; } filterset_free(fs); return noit_false; } UNLOCKFS(); return noit_false; }
static int noit_config_check_update_attrs(xmlNodePtr node, int argc, char **argv) { int i, error = 0; if(argc % 2) return -1; for(i=0; i<argc; i+=2) { void *vattrinfo; struct _valid_attr_t *attrinfo; char *attr = argv[i], *val = NULL; if(!strcasecmp(argv[i], "no")) attr = argv[i+1]; else val = argv[i+1]; if(!noit_hash_retrieve(&check_attrs, attr, strlen(attr), &vattrinfo)) { error = 1; break; } attrinfo = vattrinfo; /* The fixation stuff doesn't matter here, this check is brand-new */ xmlUnsetProp(node, (xmlChar *)attrinfo->name); if(val) xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)val); noit_conf_mark_changed(); } return error; }
noit_log_stream_t noit_log_stream_new(const char *name, const char *type, const char *path, void *ctx, noit_hash_table *config) { noit_log_stream_t ls, saved; struct _noit_log_stream tmpbuf; void *vops = NULL; ls = calloc(1, sizeof(*ls)); ls->name = strdup(name); ls->path = path ? strdup(path) : NULL; ls->type = type ? strdup(type) : NULL; ls->enabled = 1; ls->config = config; if(!type) ls->ops = NULL; else if(noit_hash_retrieve(&noit_logops, type, strlen(type), &vops)) ls->ops = vops; else goto freebail; if(ls->ops && ls->ops->openop(ls)) goto freebail; saved = noit_log_stream_find(name); if(saved) { pthread_rwlock_t *lock = saved->lock; memcpy(&tmpbuf, saved, sizeof(*saved)); memcpy(saved, ls, sizeof(*saved)); memcpy(ls, &tmpbuf, sizeof(*saved)); saved->lock = lock; ls->lock = NULL; noit_log_stream_free(ls); ls = saved; } else { /* We strdup the name *again*. We'going to kansas city shuffle the * ls later (see memcpy above). However, if don't strdup, then the * noit_log_stream_free up there will sweep our key right our from * under us. */ if(noit_hash_store(&noit_loggers, strdup(ls->name), strlen(ls->name), ls) == 0) goto freebail; ls->lock = calloc(1, sizeof(*ls->lock)); noit_log_init_rwlock(ls); } /* This is for things that don't open on paths */ if(ctx) ls->op_ctx = ctx; return ls; freebail: fprintf(stderr, "Failed to instantiate logger(%s,%s,%s)\n", name, type ? type : "[null]", path ? path : "[null]"); free(ls->name); if(ls->path) free(ls->path); if(ls->type) free(ls->type); free(ls); return NULL; }
noit_check_t * noit_poller_lookup(uuid_t in) { void *vcheck; if(noit_hash_retrieve(&polls, (char *)in, UUID_SIZE, &vcheck)) return (noit_check_t *)vcheck; return NULL; }
noit_log_stream_t noit_log_stream_find(const char *name) { void *vls; if(noit_hash_retrieve(&noit_loggers, name, strlen(name), &vls)) { return (noit_log_stream_t)vls; } return NULL; }
void * noit_console_userdata_get(struct __noit_console_closure *ncct, const char *name) { void *vitem; if(noit_hash_retrieve(&ncct->userdata, name, strlen(name), &vitem)) return ((noit_console_userdata_t *)vitem)->data; return NULL; }
static int __isactive_ci(struct dns_check_info *ci) { void *u; int exists = 0; pthread_mutex_lock(&active_events_lock); if(noit_hash_retrieve(&active_events, (void *)&ci, sizeof(ci), &u)) exists = 1; pthread_mutex_unlock(&active_events_lock); return exists; }
int noit_filter_exists(const char *name) { int exists; void *v; LOCKFS(); exists = noit_hash_retrieve(filtersets, name, strlen(name), &v); UNLOCKFS(); return exists; }
jlog_feed_stats_t * noit_jlog_feed_stats(const char *sub) { void *vs = NULL; jlog_feed_stats_t *s = NULL; if(noit_hash_retrieve(&feed_stats, sub, strlen(sub), &vs)) return (jlog_feed_stats_t *)vs; s = calloc(1, sizeof(*s)); s->feed_name = strdup(sub); noit_hash_store(&feed_stats, s->feed_name, strlen(s->feed_name), s); return s; }
static rest_request_handler noit_http_get_handler(noit_http_rest_closure_t *restc) { struct rule_container *cont = NULL; struct rest_url_dispatcher *rule; noit_http_request *req = noit_http_session_request(restc->http_ctx); const char *uri_str; const char *eoq, *eob; uri_str = noit_http_request_uri_str(req); eoq = strchr(uri_str, '?'); if(!eoq) eoq = uri_str + strlen(uri_str); eob = eoq - 1; /* find the right base */ while(1) { void *vcont; while(eob >= uri_str && *eob != '/') eob--; if(eob < uri_str) break; /* off the front */ if(noit_hash_retrieve(&dispatch_points, uri_str, eob - uri_str + 1, &vcont)) { cont = vcont; eob++; /* move past the determined base */ break; } eob--; } if(!cont) return NULL; for(rule = cont->rules; rule; rule = rule->next) { int ovector[30]; int cnt; if(strcmp(rule->method, noit_http_request_method_str(req))) continue; if((cnt = pcre_exec(rule->expression, rule->extra, eob, eoq - eob, 0, 0, ovector, sizeof(ovector)/sizeof(*ovector))) > 0) { /* We match, set 'er up */ restc->fastpath = rule->handler; restc->nparams = cnt - 1; if(restc->nparams) { restc->params = calloc(restc->nparams, sizeof(*restc->params)); for(cnt = 0; cnt < restc->nparams; cnt++) { int start = ovector[(cnt+1)*2]; int end = ovector[(cnt+1)*2+1]; restc->params[cnt] = malloc(end - start + 1); memcpy(restc->params[cnt], eob + start, end - start); restc->params[cnt][end - start] = '\0'; } } if(rule->auth && !rule->auth(restc, restc->nparams, restc->params)) return noit_http_rest_permission_denied; return restc->fastpath; } } return NULL; }
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; }
static noit_boolean noit_apply_filterrule(noit_hash_table *m, pcre *p, pcre_extra *pe, const char *subj) { int rc, ovector[30]; if(m) { void *vptr; return noit_hash_retrieve(m, subj, strlen(subj), &vptr); } if(!p) return noit_true; rc = pcre_exec(p, pe, subj, strlen(subj), 0, 0, ovector, 30); if(rc >= 0) return noit_true; return noit_false; }
static noit_hash_table * stratcon_datastore_journal_remove(struct sockaddr *remote, const char *remote_cn) { void *vhash = NULL; if(noit_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) { /* pluck it out */ noit_hash_delete(&working_sets, remote_cn, strlen(remote_cn), free, NULL); } else { noitL(noit_error, "attempted checkpoint on non-existing workingset: '%s'\n", remote_cn); } return vhash; }
noit_lua_check_info_t * get_ci(lua_State *L) { noit_lua_check_info_t *ci; lua_module_closure_t *lmc; void *v = NULL; if(noit_hash_retrieve(&noit_coros, (const char *)&L, sizeof(L), &v)) return (noit_lua_check_info_t *)v; ci = calloc(1, sizeof(*ci)); ci->coro_state = L; lua_getglobal(L, "noit_internal_lmc");; ci->lmc = lua_touserdata(L, lua_gettop(L)); lua_pop(L, 1); noitL(noit_error, "lmc -> %p\n", ci->lmc); noit_hash_store(&noit_coros, (const char *)&ci->coro_state, sizeof(ci->coro_state), ci); return ci; }
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; }
const char *eventer_name_for_callback_e(eventer_func_t f, eventer_t e) { void *vcd; struct callback_details *cd; if(noit_hash_retrieve(&__func_to_name, (char *)&f, sizeof(f), &vcd)) { cd = vcd; if(cd->functional_name && e) { char *buf; buf = pthread_getspecific(_tls_funcname_key); if(!buf) { buf = malloc(FUNCNAME_SIZE); pthread_setspecific(_tls_funcname_key, buf); } cd->functional_name(buf, FUNCNAME_SIZE, e, cd->closure); return buf; } return cd->simple_name; } return NULL; }
int noit_http_rest_register_auth(const char *method, const char *base, const char *expr, rest_request_handler f, rest_authorize_func_t auth) { void *vcont; struct rule_container *cont; struct rest_url_dispatcher *rule; const char *error; int erroffset; pcre *pcre_expr; int blen = strlen(base); /* base must end in a /, 'cause I said so */ if(blen == 0 || base[blen-1] != '/') return -1; pcre_expr = pcre_compile(expr, 0, &error, &erroffset, NULL); if(!pcre_expr) { noitL(noit_error, "Error in rest expr(%s) '%s'@%d: %s\n", base, expr, erroffset, error); return -1; } rule = calloc(1, sizeof(*rule)); rule->method = strdup(method); rule->expression = pcre_expr; rule->extra = pcre_study(rule->expression, 0, &error); rule->handler = f; rule->auth = auth; /* Make sure we have a container */ if(!noit_hash_retrieve(&dispatch_points, base, strlen(base), &vcont)) { cont = calloc(1, sizeof(*cont)); cont->base = strdup(base); noit_hash_store(&dispatch_points, cont->base, strlen(cont->base), cont); } else cont = vcont; /* Append the rule */ if(cont->rules_endptr) { cont->rules_endptr->next = rule; cont->rules_endptr = cont->rules_endptr->next; } else cont->rules = cont->rules_endptr = rule; return 0; }
static noit_hook_return_t ip_acl_hook_impl(void *closure, noit_module_t *self, noit_check_t *check, noit_check_t *cause) { char deny_msg[128]; stats_t current; noit_hash_table *config; noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k = NULL; int klen; void *data; config = noit_check_get_module_config(check, ip_acl_module_id); if(!config || config->size == 0) return NOIT_HOOK_CONTINUE; while(noit_hash_next(config, &iter, &k, &klen, &data)) { if(k) { void *dir = NULL; unsigned char mask; if(noit_hash_retrieve(&acls, k, strlen(k), &data)) { btrie *acl = data; if(check->target_family == AF_INET) { dir = noit_find_bpm_route_ipv4(acl, &check->target_addr.addr, &mask); if(dir == DENY_PTR) goto prevent; else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE; } else if(check->target_family == AF_INET6) { dir = noit_find_bpm_route_ipv6(acl, &check->target_addr.addr6, &mask); if(dir == DENY_PTR) goto prevent; else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE; } } } } return NOIT_HOOK_CONTINUE; prevent: memset(¤t, 0, sizeof(current)); current.available = NP_UNAVAILABLE; current.state = NP_BAD; gettimeofday(¤t.whence, NULL); snprintf(deny_msg, sizeof(deny_msg), "prevented by ACL '%s'", k ? k : "unknown"); current.status = deny_msg; noit_check_set_stats(check, ¤t); return NOIT_HOOK_DONE; }
struct target_session * _get_target_session(noit_module_t *self, char *target) { void *vts; struct target_session *ts; snmp_mod_config_t *conf; conf = noit_module_get_userdata(self); if(!noit_hash_retrieve(&conf->target_sessions, target, strlen(target), &vts)) { ts = calloc(1, sizeof(*ts)); ts->self = self; ts->fd = -1; ts->refcnt = 0; ts->target = strdup(target); ts->in_table = 1; noit_hash_store(&conf->target_sessions, ts->target, strlen(ts->target), ts); vts = ts; } return (struct target_session *)vts; }
struct target_session * _get_target_session(noit_module_t *self, char *target, int version) { char key[128]; void *vts; struct target_session *ts; snmp_mod_config_t *conf; conf = noit_module_get_userdata(self); snprintf(key, sizeof(key), "%s:v%d", target, version); if(!noit_hash_retrieve(&conf->target_sessions, key, strlen(key), &vts)) { ts = calloc(1, sizeof(*ts)); ts->self = self; ts->version = version; ts->fd = -1; ts->refcnt = 0; ts->target = strdup(target); ts->key = strdup(key); ts->in_table = 1; noit_hash_store(&conf->target_sessions, ts->key, strlen(ts->key), ts); vts = ts; } return (struct target_session *)vts; }
static int storage_node_quick_lookup(const char *uuid_str, const char *remote_cn, int *sid_out, int *storagenode_id_out, const char **remote_cn_out, const char **fqdn_out, const char **dsn_out) { /* only called from the main thread -- no safety issues */ void *vstr; const char *actual_remote_cn = NULL; if(remote_cn) actual_remote_cn = remote_cn; uuid_t id; uuid_parse((char *)uuid_str, id); if(noit_hash_retrieve(&uuid_map, (const char *)id, UUID_SIZE, &vstr)) { char *str = (char *)vstr; if(remote_cn && strcmp(str, remote_cn)) { /* replace with new remote */ void *key = malloc(UUID_SIZE); memcpy(key, id, UUID_SIZE); actual_remote_cn = strdup(remote_cn); noit_hash_replace(&uuid_map, key, UUID_SIZE, (void *)actual_remote_cn, free, free); } } else if(remote_cn) { void *key = malloc(UUID_SIZE); memcpy(key, id, UUID_SIZE); noit_hash_store(&uuid_map, key, UUID_SIZE, strdup(remote_cn)); } if(!actual_remote_cn) actual_remote_cn = "[[null]]"; if(sid_out) *sid_out = 0; if(storagenode_id_out) *storagenode_id_out = 0; if(remote_cn_out) *remote_cn_out = actual_remote_cn; if(fqdn_out) *fqdn_out = ""; if(dsn_out) *dsn_out = ""; 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; }
static int noit_console_show_check(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { int i, cnt; noit_conf_t_userdata_t *info; char xpath[1024]; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; noit_conf_xml_xpath(NULL, &xpath_ctxt); if(argc > 1) { nc_printf(ncct, "requires zero or one arguments\n"); return -1; } info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); /* We many not be in conf-t mode -- that's fine */ if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, argc ? argv[0] : NULL)) { nc_printf(ncct, "could not find check '%s'\n", argv[0]); return -1; } pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetIsEmpty(pobj->nodesetval)) { nc_printf(ncct, "no checks found\n"); goto out; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(info && cnt != 1) { nc_printf(ncct, "Ambiguous check specified\n"); goto out; } for(i=0; i<cnt; i++) { noit_hash_iter iter = NOIT_HASH_ITER_ZERO; const char *k; int klen; void *data; uuid_t checkid; noit_check_t *check; noit_hash_table *config; xmlNodePtr node, anode, mnode = NULL; char *uuid_conf; char *module, *value; node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid"); if(!uuid_conf || uuid_parse(uuid_conf, checkid)) { nc_printf(ncct, "%s has invalid or missing UUID!\n", (char *)xmlGetNodePath(node) + strlen("/noit")); continue; } nc_printf(ncct, "==== %s ====\n", uuid_conf); #define MYATTR(a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b)) #define INHERIT(a,n,b) \ _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b)) #define SHOW_ATTR(a) do { \ anode = NULL; \ value = NULL; \ INHERIT(a, anode, value); \ nc_attr_show(ncct, #a, node, anode, value); \ } while(0) if(!INHERIT(module, mnode, module)) module = NULL; if(MYATTR(name, anode, value)) nc_printf(ncct, " name: %s\n", value); else nc_printf(ncct, " name: %s [from module]\n", module ? module : "[undef]"); nc_attr_show(ncct, "module", node, mnode, module); SHOW_ATTR(target); SHOW_ATTR(resolve_rtype); SHOW_ATTR(period); SHOW_ATTR(timeout); SHOW_ATTR(oncheck); SHOW_ATTR(filterset); SHOW_ATTR(disable); /* Print out all the config settings */ config = noit_conf_get_hash(node, "config"); while(noit_hash_next(config, &iter, &k, &klen, &data)) { nc_printf(ncct, " config::%s: %s\n", k, (const char *)data); } noit_hash_destroy(config, free, free); free(config); check = noit_poller_lookup(checkid); if(!check) { nc_printf(ncct, " ERROR: not in running system\n"); } else { int idx = 0; nc_printf(ncct, " target_ip: %s\n", check->target_ip); nc_printf(ncct, " currently: "); if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":""); if(NOIT_CHECK_KILLED(check)) nc_printf(ncct, "%skilled", idx++?",":""); if(!NOIT_CHECK_CONFIGURED(check)) nc_printf(ncct, "%sunconfig", idx++?",":""); if(NOIT_CHECK_DISABLED(check)) nc_printf(ncct, "%sdisabled", idx++?",":""); if(!idx) nc_printf(ncct, "idle"); nc_write(ncct, "\n", 1); if(check->stats.current.whence.tv_sec == 0) { nc_printf(ncct, " last run: never\n"); } else { stats_t *c = &check->stats.current; int mcount=0; const char **sorted_keys; char buff[256]; struct timeval now, diff; noit_boolean filtered; gettimeofday(&now, NULL); sub_timeval(now, c->whence, &diff); nc_printf(ncct, " last run: %0.3f seconds ago\n", diff.tv_sec + (diff.tv_usec / 1000000.0)); nc_printf(ncct, " availability/state: %s/%s\n", noit_check_available_string(c->available), noit_check_state_string(c->state)); nc_printf(ncct, " status: %s\n", c->status ? c->status : "[[null]]"); nc_printf(ncct, " metrics:\n"); memset(&iter, 0, sizeof(iter)); sorted_keys = alloca(c->metrics.size * sizeof(*sorted_keys)); while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) { if(sorted_keys) sorted_keys[mcount++] = k; else { noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data); filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data); nc_printf(ncct, " %c%s\n", filtered ? '*' : ' ', buff); } } if(sorted_keys) { int j; qsort(sorted_keys, mcount, sizeof(*sorted_keys), _qsort_string_compare); for(j=0;j<mcount;j++) { if(noit_hash_retrieve(&c->metrics, sorted_keys[j], strlen(sorted_keys[j]), &data)) { noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data); filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data); nc_printf(ncct, " %c%s\n", filtered ? '*' : ' ', buff); } } } } } } out: if(pobj) xmlXPathFreeObject(pobj); return 0; }
static int external_handler(eventer_t e, int mask, void *closure, struct timeval *now) { noit_module_t *self = (noit_module_t *)closure; external_data_t *data; data = noit_module_get_userdata(self); while(1) { int inlen, expectlen; noit_check_t *check; struct check_info *ci; void *vci; if(!data->cr) { struct external_response r; struct msghdr msg; struct iovec v[3]; memset(&r, 0, sizeof(r)); v[0].iov_base = (char *)&r.check_no; v[0].iov_len = sizeof(r.check_no); v[1].iov_base = (char *)&r.exit_code; v[1].iov_len = sizeof(r.exit_code); v[2].iov_base = (char *)&r.stdoutlen; v[2].iov_len = sizeof(r.stdoutlen); expectlen = v[0].iov_len + v[1].iov_len + v[2].iov_len; /* Make this into a recv'ble message so we can PEEK */ memset(&msg, 0, sizeof(msg)); msg.msg_iov = v; msg.msg_iovlen = 3; inlen = recvmsg(e->fd, &msg, MSG_PEEK); if(inlen == 0) goto widowed; if((inlen == -1 && errno == EAGAIN) || (inlen > 0 && inlen < expectlen)) return EVENTER_READ | EVENTER_EXCEPTION; if(inlen == -1) noitL(noit_error, "recvmsg() failed: %s\n", strerror(errno)); assert(inlen == expectlen); while(-1 == (inlen = recvmsg(e->fd, &msg, 0)) && errno == EINTR); assert(inlen == expectlen); data->cr = calloc(sizeof(*data->cr), 1); memcpy(data->cr, &r, sizeof(r)); data->cr->stdoutbuff = malloc(data->cr->stdoutlen); } if(data->cr) { while(data->cr->stdoutlen_sofar < data->cr->stdoutlen) { while((inlen = read(e->fd, data->cr->stdoutbuff + data->cr->stdoutlen_sofar, data->cr->stdoutlen - data->cr->stdoutlen_sofar)) == -1 && errno == EINTR); if(inlen == -1 && errno == EAGAIN) return EVENTER_READ | EVENTER_EXCEPTION; if(inlen == 0) goto widowed; data->cr->stdoutlen_sofar += inlen; } assert(data->cr->stdoutbuff[data->cr->stdoutlen-1] == '\0'); if(!data->cr->stderrbuff) { while((inlen = read(e->fd, &data->cr->stderrlen, sizeof(data->cr->stderrlen))) == -1 && errno == EINTR); if(inlen == -1 && errno == EAGAIN) return EVENTER_READ | EVENTER_EXCEPTION; if(inlen == 0) goto widowed; assert(inlen == sizeof(data->cr->stderrlen)); data->cr->stderrbuff = malloc(data->cr->stderrlen); } while(data->cr->stderrlen_sofar < data->cr->stderrlen) { while((inlen = read(e->fd, data->cr->stderrbuff + data->cr->stderrlen_sofar, data->cr->stderrlen - data->cr->stderrlen_sofar)) == -1 && errno == EINTR); if(inlen == -1 && errno == EAGAIN) return EVENTER_READ | EVENTER_EXCEPTION; if(inlen == 0) goto widowed; data->cr->stderrlen_sofar += inlen; } assert(data->cr->stderrbuff[data->cr->stderrlen-1] == '\0'); } assert(data->cr && data->cr->stdoutbuff && data->cr->stderrbuff); gettimeofday(now, NULL); /* set it, as we care about accuracy */ /* Lookup data in check_no hash */ if(noit_hash_retrieve(&data->external_checks, (const char *)&data->cr->check_no, sizeof(data->cr->check_no), &vci) == 0) vci = NULL; ci = (struct check_info *)vci; /* We've seen it, it ain't coming again... * remove it, we'll free it ourselves */ noit_hash_delete(&data->external_checks, (const char *)&data->cr->check_no, sizeof(data->cr->check_no), NULL, NULL); /* If there is no timeout_event, the check must have completed. * We have nothing to do. */ if(!ci || !ci->timeout_event) { free(data->cr->stdoutbuff); free(data->cr->stderrbuff); free(data->cr); data->cr = NULL; continue; } ci->exit_code = data->cr->exit_code; ci->output = data->cr->stdoutbuff; ci->error = data->cr->stderrbuff; free(data->cr); data->cr = NULL; check = ci->check; external_log_results(self, check); eventer_remove(ci->timeout_event); free(ci->timeout_event->closure); eventer_free(ci->timeout_event); ci->timeout_event = NULL; check->flags &= ~NP_RUNNING; } widowed: noitL(noit_error, "external module terminated, must restart.\n"); exit(1); }
static int noit_console_filter_configure(noit_console_closure_t ncct, int argc, char **argv, noit_console_state_t *state, void *closure) { xmlNodePtr parent, fsnode = NULL; int rv = -1; noit_conf_t_userdata_t *info; char xpath[1024]; info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA); if(!info) { nc_printf(ncct, "internal error\n"); goto cleanup; } if(strncmp(info->path, "/filtersets/", strlen("/filtersets/")) && strcmp(info->path, "/filtersets")) { nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n", info->path); goto cleanup; } if(argc != 1) { nc_printf(ncct, "filterset requires one argument\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "/%s", info->path); parent = noit_conf_get_section(NULL, xpath); if(!parent) { nc_printf(ncct, "internal error, can't final current working path\n"); goto cleanup; } snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]); fsnode = noit_conf_get_section(parent, xpath); if(closure) { int removed; removed = noit_filter_remove(fsnode); nc_printf(ncct, "%sremoved filterset '%s'\n", removed ? "" : "failed to ", argv[0]); if(removed) { xmlUnlinkNode(fsnode); xmlFreeNode(fsnode); } rv = !removed; goto cleanup; } if(!fsnode) { void *vfs; nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]); LOCKFS(); if(noit_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) { UNLOCKFS(); nc_printf(ncct, "filter of the same name already exists\n"); goto cleanup; } UNLOCKFS(); /* Fine the parent path */ fsnode = xmlNewNode(NULL, (xmlChar *)"filterset"); xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]); xmlAddChild(parent, fsnode); nc_printf(ncct, "created new filterset\n"); } if(info) { char *xmlpath = NULL; if(info->path) free(info->path); xmlpath = (char *)xmlGetNodePath(fsnode); info->path = strdup(xmlpath + strlen("/noit")); free(xmlpath); strlcpy(info->filter_name, argv[0], sizeof(info->filter_name)); if(state) { noit_console_state_push_state(ncct, state); noit_console_state_init(ncct); } } cleanup: return rv; }
static interim_journal_t * interim_journal_get(struct sockaddr *remote, const char *remote_cn_in, int storagenode_id, const char *fqdn_in) { void *vhash, *vij; noit_hash_table *working_set; interim_journal_t *ij; struct timeval now; char jpath[PATH_MAX]; char remote_str[128]; const char *remote_cn = remote_cn_in ? remote_cn_in : "default"; const char *fqdn = fqdn_in ? fqdn_in : "default"; noit_convert_sockaddr_to_buff(remote_str, sizeof(remote_str), remote); if(!*remote_str) strlcpy(remote_str, "default", sizeof(remote_str)); /* Lookup the working set */ if(!noit_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) { working_set = calloc(1, sizeof(*working_set)); noit_hash_store(&working_sets, strdup(remote_cn), strlen(remote_cn), working_set); } else working_set = vhash; /* Lookup the interim journal within the working set */ if(!noit_hash_retrieve(working_set, fqdn, strlen(fqdn), &vij)) { ij = calloc(1, sizeof(*ij)); gettimeofday(&now, NULL); snprintf(jpath, sizeof(jpath), "%s/%s/%s/%d/%08x%08x.tmp", basejpath, remote_str, remote_cn, storagenode_id, (unsigned int)now.tv_sec, (unsigned int)now.tv_usec); ij->remote_str = strdup(remote_str); ij->remote_cn = strdup(remote_cn); ij->fqdn = fqdn_in ? strdup(fqdn_in) : NULL; ij->storagenode_id = storagenode_id; ij->filename = strdup(jpath); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); if(ij->fd < 0 && errno == ENOENT) { if(mkdir_for_file(ij->filename, 0750)) { noitL(noit_error, "Failed to create dir for '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0 && errno == EEXIST) { /* This can only occur if we crash after before checkpointing */ unlink(ij->filename); ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640); } if(ij->fd < 0) { noitL(noit_error, "Failed to open interim journal '%s': %s\n", ij->filename, strerror(errno)); exit(-1); } noit_hash_store(working_set, strdup(fqdn), strlen(fqdn), ij); } else ij = vij; return ij; }