static void dns_module_eventer_dns_utm_fn(struct dns_ctx *ctx, int timeout, void *data) { dns_ctx_handle_t *h = data; eventer_t e = NULL, newe = NULL; if(ctx == NULL) { if(h && h->timeout) e = eventer_remove(h->timeout); } else { assert(h->ctx == ctx); if(h->timeout) e = eventer_remove(h->timeout); if(timeout > 0) { newe = eventer_alloc(); newe->mask = EVENTER_TIMER; newe->callback = dns_module_invoke_timeouts; newe->closure = h; gettimeofday(&newe->whence, NULL); newe->whence.tv_sec += timeout; } } if(e) { eventer_free(e); if(h) dns_module_dns_ctx_release(h); } if(newe) { dns_module_dns_ctx_acquire(h); eventer_add(newe); } if(h) { h->timeout = newe; } }
static void dns_cache_utm_fn(struct dns_ctx *ctx, int timeout, void *data) { eventer_t e = NULL, newe = NULL; if(ctx == NULL) e = eventer_remove(dns_cache_timeout); else { if(timeout < 0) e = eventer_remove(dns_cache_timeout); else { newe = eventer_in_s_us(dns_invoke_timeouts, dns_ctx, timeout, 0); } } if(e) eventer_free(e); if(newe) eventer_add(newe); dns_cache_timeout = newe; }
static int ssh2_needs_bytes_as_libssh2_is_impatient(eventer_t e, int mask, void *closure, struct timeval *now) { ssh2_check_info_t *ci = closure; eventer_t asynch_e; if(mask & EVENTER_EXCEPTION) { noit_check_t *check = ci->check; ci->timed_out = 0; ci->error = strdup("ssh connection failed"); ssh2_log_results(ci->self, ci->check); ssh2_cleanup(ci->self, ci->check); eventer_remove_fd(e->fd); e->opset->close(e->fd, &mask, e); check->flags &= ~NP_RUNNING; return 0; } /* We steal the timeout_event as it has the exact timeout we want. */ assert(ci->timeout_event); asynch_e = eventer_remove(ci->timeout_event); assert(asynch_e); ci->timeout_event = NULL; ci->synch_fd_event = NULL; asynch_e->fd = e->fd; asynch_e->callback = ssh2_drive_session; asynch_e->closure = closure; asynch_e->mask = EVENTER_ASYNCH; eventer_add(asynch_e); eventer_remove_fd(e->fd); return 0; }
void noit_poller_free_check(noit_check_t *checker) { noit_module_t *mod; if(checker->flags & NP_RUNNING) { recycle_check(checker); return; } mod = noit_module_lookup(checker->module); if(mod->cleanup) mod->cleanup(mod, checker); if(checker->fire_event) { eventer_remove(checker->fire_event); free(checker->fire_event->closure); eventer_free(checker->fire_event); checker->fire_event = NULL; } if(checker->closure) free(checker->closure); if(checker->target) free(checker->target); if(checker->module) free(checker->module); if(checker->name) free(checker->name); if(checker->config) { noit_hash_destroy(checker->config, free, free); free(checker->config); checker->config = NULL; } free(checker); }
static void dns_cache_utm_fn(struct dns_ctx *ctx, int timeout, void *data) { eventer_t e = NULL, newe = NULL; if(ctx == NULL) e = eventer_remove(dns_cache_timeout); else { if(timeout < 0) e = eventer_remove(dns_cache_timeout); else { newe = eventer_alloc(); newe->mask = EVENTER_TIMER; newe->callback = dns_invoke_timeouts; newe->closure = dns_ctx; gettimeofday(&newe->whence, NULL); newe->whence.tv_sec += timeout; } } if(e) eventer_free(e); if(newe) eventer_add(newe); dns_cache_timeout = newe; }
static void external_cleanup(noit_module_t *self, noit_check_t *check) { struct check_info *ci = (struct check_info *)check->closure; if(ci) { if(ci->timeout_event) { eventer_remove(ci->timeout_event); free(ci->timeout_event->closure); eventer_free(ci->timeout_event); ci->timeout_event = NULL; } } }
static void eventer_dns_utm_fn(struct dns_ctx *ctx, int timeout, void *data) { dns_ctx_handle_t *h = data; eventer_t e = NULL, newe = NULL; if(ctx == NULL) e = eventer_remove(h->timeout); else { assert(h->ctx == ctx); if(timeout < 0) e = eventer_remove(h->timeout); else { newe = eventer_alloc(); newe->mask = EVENTER_TIMER; newe->callback = dns_invoke_timeouts; newe->closure = h; gettimeofday(&newe->whence, NULL); newe->whence.tv_sec += timeout; } } if(e) eventer_free(e); if(newe) eventer_add(newe); h->timeout = newe; }
static void dns_ctx_handle_free(void *vh) { dns_ctx_handle_t *h = vh; free(h->ns); eventer_remove_fd(h->e->fd); eventer_free(h->e); h->e = NULL; if(h->timeout) { eventer_remove(h->timeout); eventer_free(h->timeout); h->timeout = NULL; } dns_close(h->ctx); dns_free(h->ctx); assert(h->timeout == NULL); free(h); }
static int noit_snmp_session_cleanse(struct target_session *ts) { if(ts->refcnt == 0 && ts->sess_handle) { eventer_remove_fd(ts->fd); ts->fd = -1; if(ts->timeoutevent) { eventer_remove(ts->timeoutevent); ts->timeoutevent = NULL; } snmp_sess_close(ts->sess_handle); ts->sess_handle = NULL; if(!ts->in_table) { free(ts); } return 1; } return 0; }
static void _set_ts_timeout(struct target_session *ts, struct timeval *t) { struct timeval now; eventer_t e = NULL; if(ts->timeoutevent) { e = eventer_remove(ts->timeoutevent); ts->timeoutevent = NULL; } if(!t) return; gettimeofday(&now, NULL); if(!e) e = eventer_alloc(); e->callback = noit_snmp_session_timeout; e->closure = ts; e->mask = EVENTER_TIMER; add_timeval(now, *t, &e->whence); ts->timeoutevent = e; eventer_add(e); }
static void noit_event_dispose(void *ev) { int mask; eventer_t *value = ev; eventer_t removed, e = *value; noitL(nldeb, "lua check cleanup: dropping (%p)->fd (%d)\n", e, e->fd); removed = eventer_remove(e); noitL(nldeb, " remove from eventer system %s\n", removed ? "succeeded" : "failed"); if(e->mask & (EVENTER_READ|EVENTER_WRITE|EVENTER_EXCEPTION)) { noitL(nldeb, " closing down fd %d\n", e->fd); e->opset->close(e->fd, &mask, e); } if(e->closure) { struct nl_generic_cl *cl; cl = e->closure; if(cl->free) cl->free(cl); } eventer_free(e); free(ev); }
static void ssh2_cleanup(noit_module_t *self, noit_check_t *check) { ssh2_check_info_t *ci = check->closure; if(ci) { if(ci->timeout_event) { eventer_remove(ci->timeout_event); eventer_free(ci->timeout_event); } if(ci->session) { libssh2_session_disconnect(ci->session, "Bye!"); libssh2_session_free(ci->session); } if(ci->methods.kex) free(ci->methods.kex); if(ci->methods.hostkey) free(ci->methods.hostkey); if(ci->methods.crypt_cs) free(ci->methods.crypt_cs); if(ci->methods.crypt_sc) free(ci->methods.crypt_sc); if(ci->methods.mac_cs) free(ci->methods.mac_cs); if(ci->methods.mac_sc) free(ci->methods.mac_sc); if(ci->methods.comp_cs) free(ci->methods.comp_cs); if(ci->methods.comp_sc) free(ci->methods.comp_sc); if(ci->error) free(ci->error); memset(ci, 0, sizeof(*ci)); } }
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 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 ping_icmp_handler(eventer_t e, int mask, void *closure, struct timeval *now, u_int8_t family) { noit_module_t *self = (noit_module_t *)closure; ping_icmp_data_t *ping_data; struct check_info *data; char packet[1500]; int packet_len = sizeof(packet); union { struct sockaddr_in in4; struct sockaddr_in6 in6; } from; unsigned int from_len; struct ping_payload *payload; if(family != AF_INET && family != AF_INET6) return EVENTER_READ; ping_data = noit_module_get_userdata(self); while(1) { struct ping_session_key k; int inlen; u_int8_t iphlen = 0; void *vcheck; noit_check_t *check; struct timeval tt, whence; from_len = sizeof(from); inlen = recvfrom(e->fd, packet, packet_len, 0, (struct sockaddr *)&from, &from_len); mtev_gettimeofday(now, NULL); /* set it, as we care about accuracy */ if(inlen < 0) { if(errno == EAGAIN || errno == EINTR) break; mtevLT(nldeb, now, "ping_icmp recvfrom: %s\n", strerror(errno)); break; } if(family == AF_INET) { struct icmp *icp4; iphlen = ((struct ip *)packet)->ip_hl << 2; if((inlen-iphlen) != sizeof(struct icmp)+PING_PAYLOAD_LEN) { mtevLT(nldeb, now, "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen); continue; } icp4 = (struct icmp *)(packet + iphlen); payload = (struct ping_payload *)(icp4 + 1); if(icp4->icmp_type != ICMP_ECHOREPLY) { mtevLT(nldeb, now, "ping_icmp bad type: %d\n", icp4->icmp_type); continue; } if(icp4->icmp_id != (((vpsized_uint)self) & 0xffff)) { mtevLT(nldeb, now, "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", icp4->icmp_id, ntohs(icp4->icmp_seq), (unsigned long)(((vpsized_uint)self) & 0xffff)); continue; } } else if(family == AF_INET6) { struct icmp6_hdr *icp6 = (struct icmp6_hdr *)packet; if((inlen) != sizeof(struct icmp6_hdr)+PING_PAYLOAD_LEN) { mtevLT(nldeb, now, "ping_icmp bad size: %d+%d\n", iphlen, inlen-iphlen); continue; } payload = (struct ping_payload *)(icp6+1); if(icp6->icmp6_type != ICMP6_ECHO_REPLY) { mtevLT(nldeb, now, "ping_icmp bad type: %d\n", icp6->icmp6_type); continue; } if(icp6->icmp6_id != (((vpsized_uint)self) & 0xffff)) { mtevLT(nldeb, now, "ping_icmp not sent from this instance (%d:%d) vs. %lu\n", icp6->icmp6_id, ntohs(icp6->icmp6_seq), (unsigned long)(((vpsized_uint)self) & 0xffff)); continue; } } else { /* This should be unreachable */ continue; } check = NULL; k.addr_of_check = payload->addr_of_check; uuid_copy(k.checkid, payload->checkid); if(mtev_hash_retrieve(ping_data->in_flight, (const char *)&k, sizeof(k), &vcheck)) check = vcheck; /* make sure this check is from this generation! */ if(!check) { char uuid_str[37]; uuid_unparse_lower(payload->checkid, uuid_str); mtevLT(nldeb, now, "ping_icmp response for unknown check '%s'\n", uuid_str); continue; } if((check->generation & 0xffff) != payload->generation) { mtevLT(nldeb, now, "ping_icmp response in generation gap\n"); continue; } data = (struct check_info *)check->closure; /* If there is no timeout_event, the check must have completed. * We have nothing to do. */ if(!data->timeout_event) continue; /* Sanity check the payload */ if(payload->check_no != data->check_no) continue; if(payload->check_pack_cnt != data->expected_count) continue; if(payload->check_pack_no >= data->expected_count) continue; whence.tv_sec = payload->tv_sec; whence.tv_usec = payload->tv_usec; sub_timeval(*now, whence, &tt); data->turnaround[payload->check_pack_no] = (float)tt.tv_sec + (float)tt.tv_usec / 1000000.0; if(ping_icmp_is_complete(self, check)) { ping_icmp_log_results(self, check); eventer_remove(data->timeout_event); free(data->timeout_event->closure); eventer_free(data->timeout_event); data->timeout_event = NULL; check->flags &= ~NP_RUNNING; k.addr_of_check = (vpsized_uint)check ^ random_num; uuid_copy(k.checkid, check->checkid); mtev_hash_delete(ping_data->in_flight, (const char *)&k, sizeof(k), free, NULL); } } return EVENTER_READ; }
static void dns_cb(struct dns_ctx *ctx, void *result, void *data) { int r = dns_status(ctx); int len, i; struct dns_check_info *ci = data; struct dns_parse p; struct dns_rr rr; unsigned nrr; unsigned char dn[DNS_MAXDN]; const unsigned char *pkt, *cur, *end; char *result_str[MAX_RR] = { NULL }; char *result_combined = NULL; /* If out ci isn't active, we must have timed out already */ if(!__isactive_ci(ci)) { if(result) free(result); return; } ci->timed_out = 0; /* If we don't have a result, explode */ if (!result) { ci->error = strdup(dns_strerror(r)); goto cleanup; } /* Process the packet */ 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; while((r = dns_nextrr(&p, &rr)) > 0) { if (!dns_dnequal(dn, rr.dnsrr_dn)) continue; if ((ci->query_ctype == DNS_C_ANY || ci->query_ctype == rr.dnsrr_cls) && (ci->query_rtype == DNS_T_ANY || ci->query_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) { ci->error = strdup("protocol error"); break; } else { int32_t on = 1; /* This actually updates what we're looking for */ dns_dntodn(p.dnsp_dnbuf, ci->dn, sizeof(dn)); noit_stats_set_metric(ci->check, &ci->current, "cname", METRIC_INT32, &on); /* Now follow the leader */ noitL(nldeb, "%s. CNAME %s.\n", dns_dntosp(dn), dns_dntosp(p.dnsp_dnbuf)); dns_dntodn(p.dnsp_dnbuf, dn, sizeof(dn)); noitL(nldeb, " ---> '%s'\n", dns_dntosp(dn)); } } } if (!r && !nrr) { ci->error = strdup("no data"); } dns_rewind(&p, NULL); p.dnsp_qtyp = ci->query_rtype == DNS_T_ANY ? 0 : ci->query_rtype; p.dnsp_qcls = ci->query_ctype == DNS_C_ANY ? 0 : ci->query_ctype; while(dns_nextrr(&p, &rr) && ci->nrr < MAX_RR) decode_rr(ci, &p, &rr, &result_str[ci->nrr]); if(ci->sort) qsort(result_str, ci->nrr, sizeof(*result_str), cstring_cmp); /* calculate the length and allocate on the stack */ len = 0; for(i=0; i<ci->nrr; i++) len += strlen(result_str[i]) + 2; result_combined = alloca(len); result_combined[0] = '\0'; /* string it together */ len = 0; for(i=0; i<ci->nrr; i++) { int slen; if(i) { memcpy(result_combined + len, ", ", 2); len += 2; } slen = strlen(result_str[i]); memcpy(result_combined + len, result_str[i], slen); len += slen; result_combined[len] = '\0'; free(result_str[i]); /* free as we go */ } noit_stats_set_metric(ci->check, &ci->current, "answer", METRIC_STRING, result_combined); cleanup: if(result) free(result); if(ci->timeout_event) { eventer_t e = eventer_remove(ci->timeout_event); ci->timeout_event = NULL; if(e) eventer_free(e); } ci->check->flags &= ~NP_RUNNING; dns_check_log_results(ci); __deactivate_ci(ci); }
static int lua_web_handler(mtev_http_rest_closure_t *restc, int npats, char **pats) { int status, base, rv, mask = 0; int complete = 0; lua_web_conf_t *conf = the_one_conf; lua_module_closure_t *lmc = &conf->lmc; mtev_lua_resume_info_t *ri; mtev_lua_resume_rest_info_t *ctx = NULL; lua_State *L; eventer_t conne; mtev_http_request *req = mtev_http_session_request(restc->http_ctx); mtev_http_response *res = mtev_http_session_response(restc->http_ctx); if(!lmc || !conf || !conf->dispatch) { goto boom; } if(mtev_http_request_get_upload(req, NULL) == NULL && mtev_http_request_has_payload(req)) { const void *payload = NULL; int payload_len = 0; payload = rest_get_raw_upload(restc, &mask, &complete, &payload_len); if(!complete) return mask; mtev_http_request_set_upload(req, (char *)payload, (int64_t)payload_len, req_payload_free, NULL); restc->call_closure_free(restc->call_closure); restc->call_closure = NULL; } if(restc->call_closure == NULL) { ri = calloc(1, sizeof(*ri)); ri->bound_thread = pthread_self(); ri->context_magic = LUA_REST_INFO_MAGIC; ctx = ri->context_data = calloc(1, sizeof(mtev_lua_resume_rest_info_t)); ctx->restc = restc; ri->lmc = lmc; lua_getglobal(lmc->lua_state, "mtev_coros"); ri->coro_state = lua_newthread(lmc->lua_state); ri->coro_state_ref = luaL_ref(lmc->lua_state, -2); mtev_lua_set_resume_info(lmc->lua_state, ri); lua_pop(lmc->lua_state, 1); /* pops mtev_coros */ restc->call_closure = ri; restc->call_closure_free = rest_lua_ctx_free; } ri = restc->call_closure; ctx = ri->context_data; ctx->httpcode = 404; L = ri->coro_state; lua_getglobal(L, "require"); lua_pushstring(L, conf->dispatch); rv = lua_pcall(L, 1, 1, 0); if(rv) { int i; mtevL(mtev_error, "lua: require %s failed\n", conf->dispatch); i = lua_gettop(L); if(i>0) { if(lua_isstring(L, i)) { const char *err; size_t len; err = lua_tolstring(L, i, &len); mtevL(mtev_error, "lua: %s\n", err); } } lua_pop(L,i); goto boom; } lua_pop(L, lua_gettop(L)); mtev_lua_pushmodule(L, conf->dispatch); if(lua_isnil(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no such module"); goto boom; } lua_getfield(L, -1, "handler"); lua_remove(L, -2); if(!lua_isfunction(L, -1)) { lua_pop(L, 1); ctx->err = strdup("no 'handler' function in module"); goto boom; } mtev_lua_setup_restc(L, restc); mtev_lua_hash_to_table(L, restc->ac->config); conne = mtev_http_connection_event(mtev_http_session_connection(restc->http_ctx)); eventer_remove(conne); restc->fastpath = lua_web_restc_fastpath; status = lmc->resume(ri, 2); if(status == 0) return 0; if(mtev_http_response_complete(res) != mtev_true) { boom: mtev_http_response_standard(restc->http_ctx, (ctx && ctx->httpcode) ? ctx->httpcode : 500, "ERROR", "text/plain"); if(ctx && ctx->err) mtev_http_response_append(restc->http_ctx, ctx->err, strlen(ctx->err)); mtev_http_response_end(restc->http_ctx); } return 0; }
static int ssh2_initiate(noit_module_t *self, noit_check_t *check, noit_check_t *cause) { ssh2_check_info_t *ci = check->closure; struct timeval p_int, __now; int fd = -1, rv = -1; eventer_t e; union { struct sockaddr_in sin; struct sockaddr_in6 sin6; } sockaddr; socklen_t sockaddr_len; unsigned short ssh_port = DEFAULT_SSH_PORT; const char *port_str = NULL; /* We cannot be running */ BAIL_ON_RUNNING_CHECK(check); check->flags |= NP_RUNNING; ci->self = self; ci->check = check; ci->timed_out = 1; if(ci->timeout_event) { eventer_remove(ci->timeout_event); free(ci->timeout_event->closure); eventer_free(ci->timeout_event); ci->timeout_event = NULL; } gettimeofday(&__now, NULL); memcpy(&check->last_fire_time, &__now, sizeof(__now)); if(check->target_ip[0] == '\0') { ci->error = strdup("name resolution failure"); goto fail; } /* Open a socket */ fd = socket(check->target_family, NE_SOCK_CLOEXEC|SOCK_STREAM, 0); if(fd < 0) goto fail; /* Make it non-blocking */ if(eventer_set_fd_nonblocking(fd)) goto fail; if(noit_hash_retr_str(check->config, "port", strlen("port"), &port_str)) { ssh_port = (unsigned short)atoi(port_str); } #define config_method(a) do { \ const char *v; \ if(noit_hash_retr_str(check->config, "method_" #a, strlen("method_" #a), \ &v)) \ ci->methods.a = strdup(v); \ } while(0) config_method(kex); config_method(hostkey); config_method(crypt_cs); config_method(crypt_sc); config_method(mac_cs); config_method(mac_sc); config_method(comp_cs); config_method(comp_sc); memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sin6.sin6_family = check->target_family; if(check->target_family == AF_INET) { memcpy(&sockaddr.sin.sin_addr, &check->target_addr.addr, sizeof(sockaddr.sin.sin_addr)); sockaddr.sin.sin_port = htons(ssh_port); sockaddr_len = sizeof(sockaddr.sin); } else { memcpy(&sockaddr.sin6.sin6_addr, &check->target_addr.addr6, sizeof(sockaddr.sin6.sin6_addr)); sockaddr.sin6.sin6_port = htons(ssh_port); sockaddr_len = sizeof(sockaddr.sin6); } /* Initiate a connection */ rv = connect(fd, (struct sockaddr *)&sockaddr, sockaddr_len); if(rv == -1 && errno != EINPROGRESS) goto fail; /* Register a handler for connection completion */ e = eventer_alloc(); e->fd = fd; e->mask = EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION; e->callback = ssh2_connect_complete; e->closure = ci; ci->synch_fd_event = e; eventer_add(e); e = eventer_alloc(); e->mask = EVENTER_TIMER; e->callback = ssh2_connect_timeout; e->closure = ci; memcpy(&e->whence, &__now, sizeof(__now)); p_int.tv_sec = check->timeout / 1000; p_int.tv_usec = (check->timeout % 1000) * 1000; add_timeval(e->whence, p_int, &e->whence); ci->timeout_event = e; eventer_add(e); return 0; fail: if(fd >= 0) close(fd); ssh2_log_results(ci->self, ci->check); ssh2_cleanup(ci->self, ci->check); check->flags &= ~NP_RUNNING; return -1; }