Пример #1
0
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;
}
Пример #3
0
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;
}
Пример #4
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);
}
Пример #5
0
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;
}
Пример #6
0
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;
    }
  }
}
Пример #7
0
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;
}
Пример #8
0
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);
}
Пример #9
0
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;
}
Пример #10
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);
}
Пример #11
0
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);
}
Пример #12
0
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));
  }
}
Пример #13
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;
}
Пример #14
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);
}
Пример #15
0
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;
}
Пример #16
0
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);
}
Пример #17
0
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;
}
Пример #18
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;
}