Example #1
0
static int external_enqueue(eventer_t e, int mask, void *closure,
                            struct timeval *now) {
  external_closure_t *ecl = (external_closure_t *)closure;
  struct check_info *ci = (struct check_info *)ecl->check->closure;
  external_data_t *data;
  int fd, i;

  if(mask == EVENTER_ASYNCH_CLEANUP) {
    e->mask = 0;
    return 0;
  }
  if(!(mask & EVENTER_ASYNCH_WORK)) return 0;
  data = noit_module_get_userdata(ecl->self);
  fd = data->pipe_n2e[1];
  assert_write(fd, &ci->check_no, sizeof(ci->check_no));
  assert_write(fd, &ci->argcnt, sizeof(ci->argcnt));
  assert_write(fd, ci->arglens, sizeof(*ci->arglens)*ci->argcnt);
  for(i=0; i<ci->argcnt; i++)
    assert_write(fd, ci->args[i], ci->arglens[i]);
  assert_write(fd, &ci->envcnt, sizeof(ci->envcnt));
  assert_write(fd, ci->envlens, sizeof(*ci->envlens)*ci->envcnt);
  for(i=0; i<ci->envcnt; i++)
    assert_write(fd, ci->envs[i], ci->envlens[i]);
  return 0;
}
Example #2
0
static int
noit_lua_module_config(noit_module_t *mod,
                       mtev_hash_table *options) {
  struct module_conf *mc;
  struct module_tls_conf *mtlsc;
  LMC_DECL(L, mod, object);

  mc = noit_module_get_userdata(mod);
  if(options) {
    mtevAssert(mc->options == NULL);
    mc->options = calloc(1, sizeof(*mc->options));
    mtev_hash_init(mc->options);
    mtev_hash_merge_as_dict(mc->options, options);
  }
  else options = mc->options;
  mtlsc = __get_module_tls_conf(&mod->hdr);
  if(mtlsc->configured) return mtlsc->configured_return;

  SETUP_CALL(L, object, "config", return 0);

  noit_lua_setup_module(L, mod);
  mtev_lua_hash_to_table(L, options);
  lua_pcall(L, 2, 1, 0);

  /* If rv == 0, the caller will free options. We've
   * already freed options, that would be bad. fudge -> 1 */
  RETURN_INT(L, object, "config",
             { mtlsc->configured = 1; mtlsc->configured_return = rv; });
Example #3
0
static int noit_httptrap_init(noit_module_t *self) {
  const char *config_val;
  httptrap_mod_config_t *conf;
  conf = noit_module_get_userdata(self);

  conf->asynch_metrics = mtev_true;
  if(mtev_hash_retr_str(conf->options,
                        "asynch_metrics", strlen("asynch_metrics"),
                        (const char **)&config_val)) {
    if(!strcasecmp(config_val, "false") || !strcasecmp(config_val, "off"))
      conf->asynch_metrics = mtev_false;
  }

  httptrap_surrogate = mtev_false;
  if(mtev_hash_retr_str(conf->options,
                        "surrogate", strlen("surrogate"),
                        (const char **)&config_val)) {
    if(!strcasecmp(config_val, "true") || !strcasecmp(config_val, "on"))
      httptrap_surrogate = mtev_true;
  }

  noit_module_set_userdata(self, conf);

  /* register rest handler */
  mtev_http_rest_register("PUT", "/module/httptrap/",
                          "^(" UUID_REGEX ")/([^/]*).*$",
                          rest_httptrap_handler);
  mtev_http_rest_register("POST", "/module/httptrap/",
                          "^(" UUID_REGEX ")/([^/]*).*$",
                          rest_httptrap_handler);
  return 0;
}
Example #4
0
static int
statsd_handler(eventer_t e, int mask, void *closure,
               struct timeval *now) {
  noit_module_t *self = (noit_module_t *)closure;
  int packets_per_cycle;
  statsd_mod_config_t *conf;
  noit_check_t *parent = NULL;

  conf = noit_module_get_userdata(self);
  if(conf->primary_active) parent = noit_poller_lookup(conf->primary);

  packets_per_cycle = MAX(conf->packets_per_cycle, 1);
  for( ; packets_per_cycle > 0; packets_per_cycle--) {
    noit_check_t *checks[MAX_CHECKS];
    int nchecks = 0;
    char ip[INET6_ADDRSTRLEN];
    union {
      struct sockaddr_in in;
      struct sockaddr_in6 in6;
    } addr;
    socklen_t addrlen = sizeof(addr);
    ssize_t len;
    uuid_t check_id;
    len = recvfrom(e->fd, conf->payload, conf->payload_len-1, 0,
                   (struct sockaddr *)&addr, &addrlen);
    if(len < 0) {
      if(errno != EAGAIN)
        noitL(nlerr, "statsd: recvfrom() -> %s\n", strerror(errno));
      break;
    }
    switch(addr.in.sin_family) {
      case AF_INET:
        addrlen = sizeof(struct sockaddr_in);
        inet_ntop(AF_INET, &((struct sockaddr_in *)&addr)->sin_addr, ip, addrlen);
        break;
      case AF_INET6:
        addrlen = sizeof(struct sockaddr_in6);
        inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, ip, addrlen);
        break;
      default:
        ip[0] = '\0';
    }
    conf->payload[len] = '\0';
    nchecks = 0;
    if(*ip)
      nchecks = noit_poller_lookup_by_ip_module(ip, self->hdr.name,
                                                checks, MAX_CHECKS-1);
    noitL(nldeb, "statsd(%d bytes) from '%s' -> %d checks%s\n", (int)len,
          ip, (int)nchecks, parent ? " + a parent" : "");
    if(parent) checks[nchecks++] = parent;
    if(nchecks)
      statsd_handle_payload(checks, nchecks, conf->payload, len);
  }
  return EVENTER_READ | EVENTER_EXCEPTION;
}
Example #5
0
static int
statsd_submit(noit_module_t *self, noit_check_t *check,
              noit_check_t *cause) {
  statsd_closure_t *ccl;
  struct timeval duration;
  statsd_mod_config_t *conf;

  conf = noit_module_get_userdata(self);
  if(!conf->primary_active) conf->check = NULL;
  if(0 == memcmp(conf->primary, check->checkid, sizeof(uuid_t))) {
    conf->check = check;
    if(NOIT_CHECK_DISABLED(check) || NOIT_CHECK_KILLED(check)) {
      conf->check = NULL;
      return 0;
    }
  }

  /* We are passive, so we don't do anything for transient checks */
  if(check->flags & NP_TRANSIENT) return 0;

  if(!check->closure) {
    ccl = check->closure = calloc(1, sizeof(*ccl));
    ccl->self = self;
    memset(&check->stats.inprogress, 0, sizeof(check->stats.inprogress));
  } else {
    // Don't count the first run
    char human_buffer[256];
    ccl = (statsd_closure_t*)check->closure;
    gettimeofday(&check->stats.inprogress.whence, NULL);
    sub_timeval(check->stats.inprogress.whence, check->last_fire_time, &duration);
    check->stats.inprogress.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;

    snprintf(human_buffer, sizeof(human_buffer),
             "dur=%d,run=%d,stats=%d", check->stats.inprogress.duration,
             check->generation, ccl->stats_count);
    noitL(nldeb, "statsd(%s) [%s]\n", check->target, human_buffer);

    // Not sure what to do here
    check->stats.inprogress.available = (ccl->stats_count > 0) ?
        NP_AVAILABLE : NP_UNAVAILABLE;
    check->stats.inprogress.state = (ccl->stats_count > 0) ?
        NP_GOOD : NP_BAD;
    check->stats.inprogress.status = human_buffer;
    if(check->last_fire_time.tv_sec)
      noit_check_passive_set_stats(check, &check->stats.inprogress);

    memcpy(&check->last_fire_time, &check->stats.inprogress.whence, sizeof(duration));
  }
  ccl->stats_count = 0;
  noit_check_stats_clear(check, &check->stats.inprogress);
  return 0;
}
Example #6
0
static int noit_statsd_config(noit_module_t *self, noit_hash_table *options) {
  statsd_mod_config_t *conf;
  conf = noit_module_get_userdata(self);
  if(conf) {
    if(conf->options) {
      noit_hash_destroy(conf->options, free, free);
      free(conf->options);
    }
  }
  else
    conf = calloc(1, sizeof(*conf));
  conf->options = options;
  noit_module_set_userdata(self, conf);
  return 1;
}
Example #7
0
static int dns_module_init(noit_module_t *self) {
  const struct dns_nameval *nv;
  struct dns_ctx *pctx;
  int i;
  const char *config_val;
  dns_mod_config_t *conf;

  conf = noit_module_get_userdata(self);

  pthread_mutex_init(&dns_ctx_store_lock, NULL);
  pthread_mutex_init(&active_events_lock, NULL);

  conf->contexts = DEFAULT_MAX_CONTEXTS;
  if(noit_hash_retr_str(conf->options,
                         "contexts", strlen("contexts"),
                         (const char**)&config_val)) {
    conf->contexts = atoi(config_val);
    if (conf->contexts <= 0)
      conf->contexts = DEFAULT_MAX_CONTEXTS;
  }
  /* HASH the rr types */
  for(i=0, nv = dns_type_index(i); nv->name; nv = dns_type_index(++i))
    noit_hash_store(&dns_rtypes,
                    nv->name, strlen(nv->name),
                    (void *)nv);
  /* HASH the class types */
  for(i=0, nv = dns_class_index(i); nv->name; nv = dns_class_index(++i))
    noit_hash_store(&dns_ctypes,
                    nv->name, strlen(nv->name),
                    (void *)nv);

  noit_check_interpolate_register_oper_fn("inaddrarpa",
                                          dns_interpolate_inaddr_arpa);
  noit_check_interpolate_register_oper_fn("reverseip",
                                          dns_interpolate_reverse_ip);

  if (dns_init(NULL, 0) < 0 || (pctx = dns_new(NULL)) == NULL) {
    noitL(nlerr, "Unable to initialize dns subsystem\n");
    return -1;
  }
  dns_free(pctx);
  if(dns_module_dns_ctx_alloc(self, NULL, 0) == NULL) {
    noitL(nlerr, "Error setting up default dns resolver context.\n");
    return -1;
  }
  register_console_dns_commands();
  return 0;
}
Example #8
0
static int external_config(noit_module_t *self, noit_hash_table *options) {
  external_data_t *data;
  data = noit_module_get_userdata(self);
  if(data) {
    if(data->options) {
      noit_hash_destroy(data->options, free, free);
      free(data->options);
    }
  }
  else
    data = calloc(1, sizeof(*data));
  data->options = options;
  if(!data->options) data->options = calloc(1, sizeof(*data->options));
  noit_module_set_userdata(self, data);
  return 1;
}
Example #9
0
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;
}
Example #10
0
static int ping_icmp_timeout(eventer_t e, int mask,
                             void *closure, struct timeval *now) {
  struct ping_closure *pcl = (struct ping_closure *)closure;
  struct ping_session_key k;
  struct check_info *data;
  ping_icmp_data_t *ping_data;

  if(!NOIT_CHECK_KILLED(pcl->check) && !NOIT_CHECK_DISABLED(pcl->check)) {
    ping_icmp_log_results(pcl->self, pcl->check);
  }
  data = (struct check_info *)pcl->check->closure;
  data->timeout_event = NULL;
  pcl->check->flags &= ~NP_RUNNING;
  ping_data = noit_module_get_userdata(pcl->self);
  k.addr_of_check = (vpsized_uint)pcl->check ^ random_num;
  uuid_copy(k.checkid, pcl->check->checkid);
  mtev_hash_delete(ping_data->in_flight, (const char *)&k, sizeof(k),
                   free, NULL);
  free(pcl);
  return 0;
}
Example #11
0
static mtev_boolean
mtev_httptrap_check_aynsch(noit_module_t *self,
                           noit_check_t *check) {
  const char *config_val;
  httptrap_mod_config_t *conf;
  if(!self) return mtev_true;
  conf = noit_module_get_userdata(self);
  if(!conf) return mtev_true;
  mtev_boolean is_asynch = conf->asynch_metrics;
  if(mtev_hash_retr_str(check->config,
                        "asynch_metrics", strlen("asynch_metrics"),
                        (const char **)&config_val)) {
    if(!strcasecmp(config_val, "false") || !strcasecmp(config_val, "off"))
      is_asynch = mtev_false;
    else if(!strcasecmp(config_val, "true") || !strcasecmp(config_val, "on"))
      is_asynch = mtev_true;
  }

  if(is_asynch) check->flags |= NP_SUPPRESS_METRICS;
  else check->flags &= ~NP_SUPPRESS_METRICS;
  return is_asynch;
}
Example #12
0
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;
}
Example #13
0
static int external_init(noit_module_t *self) {
  external_data_t *data;

  data = noit_module_get_userdata(self);
  if(!data) data = malloc(sizeof(*data));
  data->nlerr = noit_log_stream_find("error/external");
  data->nldeb = noit_log_stream_find("debug/external");

  data->jobq = calloc(1, sizeof(*data->jobq));
  eventer_jobq_init(data->jobq, "external");
  data->jobq->backq = eventer_default_backq();
  eventer_jobq_increase_concurrency(data->jobq);

  if(socketpair(AF_UNIX, SOCK_STREAM, 0, data->pipe_n2e) != 0 ||
     socketpair(AF_UNIX, SOCK_STREAM, 0, data->pipe_e2n) != 0) {
    noitL(noit_error, "external: pipe() failed: %s\n", strerror(errno));
    return -1;
  }

  data->child = fork();
  if(data->child == -1) {
    /* No child, bail. */
    noitL(noit_error, "external: fork() failed: %s\n", strerror(errno));
    return -1;
  }

  /* parent must close the read side of n2e and the write side of e2n */
  /* The child must do the opposite */
  close(data->pipe_n2e[(data->child == 0) ? 1 : 0]);
  close(data->pipe_e2n[(data->child == 0) ? 0 : 1]);

  /* Now the parent must set its bits non-blocking, the child need not */
  if(data->child != 0) {
    /* in the parent */
    if(eventer_set_fd_nonblocking(data->pipe_e2n[0]) == -1) {
      close(data->pipe_n2e[1]);
      close(data->pipe_e2n[0]);
      noitL(noit_error,
            "external: could not set pipe non-blocking: %s\n",
            strerror(errno));
      return -1;
    }
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = data->pipe_e2n[0];
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = external_handler;
    newe->closure = self;
    eventer_add(newe);
  }
  else {
    const char *user = NULL, *group = NULL;
    if(data->options) {
      noit_hash_retr_str(data->options, "user", 4, &user);
      noit_hash_retr_str(data->options, "group", 4, &group);
    }
    noit_security_usergroup(user, group, noit_false);
    exit(external_child(data));
  }
  noit_module_set_userdata(self, data);
  return 0;
}
Example #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);
}
Example #15
0
static void external_log_results(noit_module_t *self, noit_check_t *check) {
  external_data_t *data;
  struct check_info *ci;
  stats_t current;
  struct timeval duration;

  noit_check_stats_clear(&current);

  data = noit_module_get_userdata(self);
  ci = (struct check_info *)check->closure;

  noitL(data->nldeb, "external(%s) (timeout: %d, exit: %x)\n",
        check->target, ci->timedout, ci->exit_code);

  gettimeofday(&current.whence, NULL);
  sub_timeval(current.whence, check->last_fire_time, &duration);
  current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
  if(ci->timedout) {
    current.available = NP_UNAVAILABLE;
    current.state = NP_BAD;
  }
  else if(WEXITSTATUS(ci->exit_code) == 3) {
    current.available = NP_UNKNOWN;
    current.state = NP_UNKNOWN;
  }
  else {
    current.available = NP_AVAILABLE;
    current.state = (WEXITSTATUS(ci->exit_code) == 0) ? NP_GOOD : NP_BAD;
  }

  /* Hack the output into metrics */
  if(ci->output && ci->matcher) {
    int rc, len, startoffset = 0;
    int ovector[30];
    len = strlen(ci->output);
    noitL(data->nldeb, "going to match output at %d/%d\n", startoffset, len);
    while((rc = pcre_exec(ci->matcher, NULL, ci->output, len, startoffset, 0,
                          ovector, sizeof(ovector)/sizeof(*ovector))) > 0) {
      char metric[128];
      char value[128];
      startoffset = ovector[1];
      noitL(data->nldeb, "matched at offset %d\n", rc);
      if(pcre_copy_named_substring(ci->matcher, ci->output, ovector, rc,
                                   "key", metric, sizeof(metric)) > 0 &&
         pcre_copy_named_substring(ci->matcher, ci->output, ovector, rc,
                                   "value", value, sizeof(value)) > 0) {
        /* We're able to extract something... */
        noit_stats_set_metric(&current, metric, METRIC_GUESS, value);
      }
      noitL(data->nldeb, "going to match output at %d/%d\n", startoffset, len);
    }
    noitL(data->nldeb, "match failed.... %d\n", rc);
  }

  current.status = ci->output;
  noit_check_set_stats(self, check, &current);

  /* If we didn't exit normally, or we core, or we have stderr to report...
   * provide a full report.
   */
  if((WTERMSIG(ci->exit_code) != SIGQUIT && WTERMSIG(ci->exit_code) != 0) ||
     WCOREDUMP(ci->exit_code) ||
     (ci->error && *ci->error)) {
    char uuid_str[37];
    uuid_unparse_lower(check->checkid, uuid_str);
    noitL(data->nlerr, "external/%s: (sig:%d%s) [%s]\n", uuid_str,
          WTERMSIG(ci->exit_code), WCOREDUMP(ci->exit_code)?", cored":"",
          ci->error ? ci->error : "");
  }
}
Example #16
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;
}
Example #17
0
static dns_ctx_handle_t *dns_module_dns_ctx_alloc(noit_module_t *self, const char *ns, int port) {
  void *vh;
  char *hk = NULL;
  dns_mod_config_t *conf = noit_module_get_userdata(self);
  int randkey = random() % conf->contexts;
  dns_ctx_handle_t *h = NULL;
  if(ns && *ns == '\0') ns = NULL;
  pthread_mutex_lock(&dns_ctx_store_lock);
  if(ns == NULL && default_ctx_handle != NULL) {
    /* special case -- default context */
    h = default_ctx_handle;
    dns_module_dns_ctx_acquire(h);
    goto bail;
  }

  if (ns != NULL) {
    int len = snprintf(NULL, 0, "%s:%d:%d", ns, port, randkey); 
    hk = (char *)malloc(len+1);
    snprintf(hk, len+1, "%s:%d:%d", ns, port, randkey);
  }

  if(ns &&
     noit_hash_retrieve(&dns_ctx_store, hk, strlen(hk), &vh)) {
    h = (dns_ctx_handle_t *)vh;
    dns_module_dns_ctx_acquire(h);
    free(hk);
  }
  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) {
      noitL(nlerr, "dns_init failed\n");
      failed++;
    }
    dns_set_dbgfn(h->ctx, dns_debug_wrap);
    if(ns) {
      if(dns_add_serv(h->ctx, NULL) < 0) {
        noitL(nlerr, "dns_add_serv(NULL) failed\n");
        failed++;
      }
      if(dns_add_serv(h->ctx, ns) < 0) {
        noitL(nlerr, "dns_add_serv(%s) failed\n", ns);
        failed++;
      }
    }
    if(port && port != DNS_PORT) {
      dns_set_opt(h->ctx, DNS_OPT_PORT, port);
    }
    if(dns_open(h->ctx) < 0) {
      noitL(nlerr, "dns_open failed\n");
      failed++;
    }
    if(failed) {
      free(h->ns);
      dns_free(h->ctx);
      free(h);
      free(hk);
      h = NULL;
      goto bail;
    }
    h->hkey = hk;
    dns_set_tmcbck(h->ctx, dns_module_eventer_dns_utm_fn, h);
    h->e = eventer_alloc();
    h->e->mask = EVENTER_READ | EVENTER_EXCEPTION;
    h->e->closure = h;
    h->e->callback = dns_module_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->hkey, strlen(h->hkey), h);
  }
 bail:
  pthread_mutex_unlock(&dns_ctx_store_lock);
  return h;
}
Example #18
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;
}
Example #19
0
static int noit_statsd_init(noit_module_t *self) {
  unsigned short port = 8125;
  int packets_per_cycle = 100;
  int payload_len = 256*1024;
  struct sockaddr_in skaddr;
  int sockaddr_len;
  const char *config_val;
  statsd_mod_config_t *conf;
  conf = noit_module_get_userdata(self);

  eventer_name_callback("statsd/statsd_handler", statsd_handler);

  if(noit_hash_retr_str(conf->options, "check", strlen("check"),
                        (const char **)&config_val)) {
    if(uuid_parse((char *)config_val, conf->primary) != 0)
      noitL(noit_error, "statsd check isn't a UUID\n");
    conf->primary_active = 1;
    conf->check = NULL;
  }
  if(noit_hash_retr_str(conf->options, "port", strlen("port"),
                        (const char **)&config_val)) {
    port = atoi(config_val);
  }
  conf->port = port;

  if(noit_hash_retr_str(conf->options, "packets_per_cycle",
                        strlen("packets_per_cycle"),
                        (const char **)&config_val)) {
    packets_per_cycle = atoi(config_val);
  }
  conf->packets_per_cycle = packets_per_cycle;

  conf->payload_len = payload_len;
  conf->payload = malloc(conf->payload_len);
  if(!conf->payload) {
    noitL(noit_error, "statsd malloc() failed\n");
    return -1;
  }

  conf->ipv4_fd = socket(PF_INET, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP);
  if(conf->ipv4_fd < 0) {
    noitL(noit_error, "statsd: socket failed: %s\n", strerror(errno));
    return -1;
  }
  else {
    if(eventer_set_fd_nonblocking(conf->ipv4_fd)) {
      close(conf->ipv4_fd);
      conf->ipv4_fd = -1;
      noitL(noit_error,
            "collectd: could not set socket non-blocking: %s\n",
            strerror(errno));
      return -1;
    }
  }
  memset(&skaddr, 0, sizeof(skaddr));
  skaddr.sin_family = AF_INET;
  skaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  skaddr.sin_port = htons(conf->port);
  sockaddr_len = sizeof(skaddr);
  if(bind(conf->ipv4_fd, (struct sockaddr *)&skaddr, sockaddr_len) < 0) {
    noitL(noit_error, "bind failed[%d]: %s\n", conf->port, strerror(errno));
    close(conf->ipv4_fd);
    return -1;
  }

  if(conf->ipv4_fd >= 0) {
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = conf->ipv4_fd;
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = statsd_handler;
    newe->closure = self;
    eventer_add(newe);
  }

  conf->ipv6_fd = socket(AF_INET6, NE_SOCK_CLOEXEC|SOCK_DGRAM, IPPROTO_UDP);
  if(conf->ipv6_fd < 0) {
    noitL(noit_error, "statsd: IPv6 socket failed: %s\n",
          strerror(errno));
  }
  else {
    if(eventer_set_fd_nonblocking(conf->ipv6_fd)) {
      close(conf->ipv6_fd);
      conf->ipv6_fd = -1;
      noitL(noit_error,
            "statsd: could not set socket non-blocking: %s\n",
            strerror(errno));
    }
    else {
      struct sockaddr_in6 skaddr6;
      struct in6_addr in6addr_any;
      sockaddr_len = sizeof(skaddr6);
      memset(&skaddr6, 0, sizeof(skaddr6));
      skaddr6.sin6_family = AF_INET6;
      memset(&in6addr_any, 0, sizeof(in6addr_any));
      skaddr6.sin6_addr = in6addr_any;
      skaddr6.sin6_port = htons(conf->port);

      if(bind(conf->ipv6_fd, (struct sockaddr *)&skaddr6, sockaddr_len) < 0) {
        noitL(noit_error, "bind(IPv6) failed[%d]: %s\n",
              conf->port, strerror(errno));
        close(conf->ipv6_fd);
        conf->ipv6_fd = -1;
      }
    }
  }

  if(conf->ipv6_fd >= 0) {
    eventer_t newe;
    newe = eventer_alloc();
    newe->fd = conf->ipv6_fd;
    newe->mask = EVENTER_READ | EVENTER_EXCEPTION;
    newe->callback = statsd_handler;
    newe->closure = self;
    eventer_add(newe);
  }

  noit_module_set_userdata(self, conf);
  return 0;
}