예제 #1
0
static eventer_t eventer_kqueue_impl_remove(eventer_t e) {
  eventer_t removed = NULL;
  if(e->mask & EVENTER_ASYNCH) {
    abort();
  }
  if(e->mask & (EVENTER_READ | EVENTER_WRITE | EVENTER_EXCEPTION)) {
    ev_lock_state_t lockstate;
    lockstate = acquire_master_fd(e->fd);
    noitL(eventer_deb, "kqueue: remove(%d)\n", e->fd);
    if(e == master_fds[e->fd].e) {
      removed = e;
      master_fds[e->fd].e = NULL;
      if(e->mask & (EVENTER_READ | EVENTER_EXCEPTION))
        ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);
      if(e->mask & (EVENTER_WRITE))
        ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);
    } else
      noitL(eventer_deb, "kqueue: remove(%d) failed.\n", e->fd);
    release_master_fd(e->fd, lockstate);
  }
  else if(e->mask & EVENTER_TIMER) {
    removed = eventer_remove_timed(e);
  }
  else if(e->mask & EVENTER_RECURRENT) {
    removed = eventer_remove_recurrent(e);
  }
  else {
    abort();
  }
  return removed;
}
예제 #2
0
static void postgres_ingest_stats(postgres_check_info_t *ci) {
  if(ci->rv == PGRES_TUPLES_OK) {
    /* metrics */
    int nrows, ncols, i, j;
    nrows = PQntuples(ci->result);
    ncols = PQnfields(ci->result);
    noit_stats_set_metric(&ci->current, "row_count", METRIC_INT32, &nrows);
    for (i=0; i<nrows; i++) {
      noitL(nldeb, "postgres: row %d [%d cols]:\n", i, ncols);
      if(ncols<2) continue;
      if(PQgetisnull(ci->result, i, 0)) continue;
      for (j=1; j<ncols; j++) {
        Oid coltype;
        int iv, *piv;
        int64_t lv, *plv;
        double dv, *pdv;
        char *sv;
        char mname[128];
  
        snprintf(mname, sizeof(mname), "%s`%s",
                 PQgetvalue(ci->result, i, 0), PQfname(ci->result, j));
        coltype = PQftype(ci->result, j);
        noitL(nldeb, "postgres:   col %d (%s) type %d:\n", j, mname, coltype);
        switch(coltype) {
          case BOOLOID:
            if(PQgetisnull(ci->result, i, j)) piv = NULL;
            else {
              iv = strcmp(PQgetvalue(ci->result, i, j), "f") ? 1 : 0;
              piv = &iv;
            }
            noit_stats_set_metric(&ci->current, mname, METRIC_INT32, piv);
            break;
          case INT2OID:
          case INT4OID:
          case INT8OID:
            if(PQgetisnull(ci->result, i, j)) plv = NULL;
            else {
              lv = strtoll(PQgetvalue(ci->result, i, j), NULL, 10);
              plv = &lv;
            }
            noit_stats_set_metric(&ci->current, mname, METRIC_INT64, plv);
          case FLOAT4OID:
          case FLOAT8OID:
          case NUMERICOID:
            if(PQgetisnull(ci->result, i, j)) pdv = NULL;
            else {
              dv = atof(PQgetvalue(ci->result, i, j));
              pdv = &dv;
            }
            noit_stats_set_metric(&ci->current, mname, METRIC_DOUBLE, pdv);
          default:
            if(PQgetisnull(ci->result, i, j)) sv = NULL;
            else sv = PQgetvalue(ci->result, i, j);
            noit_stats_set_metric(&ci->current, mname, METRIC_GUESS, sv);
            break;
        }
      }
    }
  }
}
예제 #3
0
static void
stratcon_datastore_journal(struct sockaddr *remote,
                           const char *remote_cn, char *line) {
  interim_journal_t *ij = NULL;
  char uuid_str[UUID_STR_LEN+1], *cp1, *cp2;
  char rtype[256];
  const char *fqdn = NULL, *dsn = NULL;
  int storagenode_id = 0;
  uuid_t checkid;
  if(!line) {
    noitL(noit_error, "Error: Line not found for %s in stratcon_datastore_journal\n", remote_cn);
    return;
  }
  cp1 = strchr(line, '\t');
  *rtype = '\0';
  if(cp1 && cp1 - line < sizeof(rtype) - 1) {
    memcpy(rtype, line, cp1 - line);
    rtype[cp1 - line] = '\0';
  }
  /* if it is a UUID based thing, find the storage node */
  switch(*rtype) {
    case 'C':
    case 'S':
    case 'M':
    case 'D':
    case 'B':
    case 'H':
      if((cp1 = strchr(cp1+1, '\t')) != NULL &&
         (cp2 = strchr(cp1+1, '\t')) != NULL &&
         (cp2-cp1 >= UUID_STR_LEN)) {
        strlcpy(uuid_str, cp2 - UUID_STR_LEN, sizeof(uuid_str));
        if(!uuid_parse(uuid_str, checkid)) {
          ingestor->storage_node_lookup(uuid_str, remote_cn, NULL,
                                        &storagenode_id, NULL,
                                        &fqdn, &dsn);
          ij = interim_journal_get(remote, remote_cn, storagenode_id, fqdn);
        }
      }
      break;
    case 'n':
      ij = interim_journal_get(remote,remote_cn,0,NULL);
      break;
    default:
      noitL(noit_error, "Error: Line has bad type for %s in stratcon_datastore_journal (%s)\n", remote_cn, line);
      break;
  }
  if(!ij) {
    noitL(ingest_err, "%d\t%s\n", storagenode_id, line);
  }
  else {
    int len;
    len = write(ij->fd, line, strlen(line));
    if(len < 0) {
      noitL(noit_error, "write to %s failed: %s\n",
            ij->filename, strerror(errno));
    }
  }
  free(line);
  return;
}
예제 #4
0
static int dns_module_init(noit_module_t *self) {
  const struct dns_nameval *nv;
  struct dns_ctx *pctx;
  int i;
  pthread_mutex_init(&dns_ctx_store_lock, NULL);
  pthread_mutex_init(&active_events_lock, NULL);
  /* 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_ctx_alloc(NULL, 0) == NULL) {
    noitL(nlerr, "Error setting up default dns resolver context.\n");
    return -1;
  }
  return 0;
}
예제 #5
0
static int
noit_check_recur_handler(eventer_t e, int mask, void *closure,
                              struct timeval *now) {
  recur_closure_t *rcl = closure;
  int ms;
  rcl->check->fire_event = NULL; /* This is us, we get free post-return */
  noit_check_resolve(rcl->check);
  ms = noit_check_schedule_next(rcl->self, NULL, rcl->check, now,
                                rcl->dispatch, NULL);
  if(NOIT_CHECK_RESOLVED(rcl->check)) {
    if(NOIT_HOOK_CONTINUE ==
       check_preflight_hook_invoke(rcl->self, rcl->check, rcl->cause)) {
      if(NOIT_CHECK_DISPATCH_ENABLED()) {
        char id[UUID_STR_LEN+1];
        uuid_unparse_lower(rcl->check->checkid, id);
        NOIT_CHECK_DISPATCH(id, rcl->check->module, rcl->check->name,
                            rcl->check->target);
      }
      if(ms < rcl->check->timeout && !(rcl->check->flags & NP_TRANSIENT))
        noitL(noit_error, "%s might not finish in %dms (timeout %dms)\n",
              rcl->check->name, ms, rcl->check->timeout);
      rcl->dispatch(rcl->self, rcl->check, rcl->cause);
    }
    check_postflight_hook_invoke(rcl->self, rcl->check, rcl->cause);
  }
  else
    noitL(noit_debug, "skipping %s`%s`%s, unresolved\n",
          rcl->check->target, rcl->check->module, rcl->check->name);
  free(rcl);
  return 0;
}
예제 #6
0
static void
stratcon_ingestor_submit_lookup(struct realtime_tracker *rt,
                                eventer_t completion) {
  struct realtime_tracker *node;

  for(node = rt; node; node = node->next) {
    char uuid_str[UUID_STR_LEN+1];
    const char *fqdn, *dsn, *remote_cn;
    char remote_ip[32];
    int storagenode_id;

    uuid_unparse_lower(node->checkid, uuid_str);
    if(storage_node_quick_lookup(uuid_str, NULL, &node->sid,
                                 &storagenode_id, &remote_cn, &fqdn, &dsn))
      continue;

    noitL(noit_debug, "stratcon_ingest_find <- (%d, %s) @ %s\n",
          node->sid, remote_cn ? remote_cn : "(null)", dsn ? dsn : "(null)");

    if(stratcon_find_noit_ip_by_cn(remote_cn,
                                   remote_ip, sizeof(remote_ip)) == 0) {
      node->noit = strdup(remote_ip);
      noitL(noit_debug, "lookup(cache): %s -> %s\n", remote_cn, node->noit);
      continue;
    }
  }
  eventer_add(completion);
}
예제 #7
0
static void eventer_ports_impl_add(eventer_t e) {
  assert(e->mask);
  ev_lock_state_t lockstate;
  const char *cbname;
  cbname = eventer_name_for_callback(e->callback);

  if(e->mask & EVENTER_ASYNCH) {
    noitL(eventer_deb, "debug: eventer_add asynch (%s)\n", cbname ? cbname : "???");
    eventer_add_asynch(NULL, e);
    return;
  }

  /* Recurrent delegation */
  if(e->mask & EVENTER_RECURRENT) {
    noitL(eventer_deb, "debug: eventer_add recurrent (%s)\n", cbname ? cbname : "???");
    eventer_add_recurrent(e);
    return;
  }

  /* Timed events are simple */
  if(e->mask & EVENTER_TIMER) {
    eventer_add_timed(e);
    return;
  }

  /* file descriptor event */
  noitL(eventer_deb, "debug: eventer_add fd (%s,%d,0x%04x)\n", cbname ? cbname : "???", e->fd, e->mask);
  lockstate = acquire_master_fd(e->fd);
  assert(e->whence.tv_sec == 0 && e->whence.tv_usec == 0);
  master_fds[e->fd].e = e;
  alter_fd(e, e->mask);
  release_master_fd(e->fd, lockstate);
}
예제 #8
0
static int
stratcon_ingest_launch_file_ingestion(const char *path,
                                      const char *remote_str,
                                      const char *remote_cn,
                                      const char *id_str) {
  char msg[PATH_MAX + 7], hfile[PATH_MAX]; /*file:\r\n*/
  if(strcmp(path + strlen(path) - 2, ".h")) {
    snprintf(hfile, sizeof(hfile), "%s.h", path);
    if(link(path, hfile) < 0 && errno != EEXIST) {
      noitL(noit_error, "cannot link journal %s: %s\n", path, strerror(errno));
      return -1;
    }
  }
  else
    strlcpy(hfile, path, sizeof(hfile));

  noitL(noit_debug, " handoff -> %s\n", hfile);
  pthread_mutex_lock(&http_ctx_lock);
  if(the_one_and_only) {
    noit_http_session_ctx *ctx = the_one_and_only;
    snprintf(msg, sizeof(msg), "file:%s\r\n", hfile);
    if(noit_http_response_append(ctx,msg,strlen(msg)) == noit_false ||
       noit_http_response_flush(ctx, noit_false) == noit_false) {
      noitL(noit_error, "handoff endpoint disconnected\n");
      the_one_and_only = NULL;
    }
  }
  pthread_mutex_unlock(&http_ctx_lock);
  return 0;
}
예제 #9
0
void
noit_console_closure_free(void *vncct) {
  noit_console_closure_t ncct = (noit_console_closure_t) vncct;
  noit_log_stream_t lf;
  noitL(noit_debug, "ncct free(%p)\n", (void *)ncct);
  if(ncct->el) el_end(ncct->el);
  if(ncct->hist) {
    history_end(ncct->hist);
    noitL(noit_debug, "ncct free->hist(%p)\n", (void *)ncct->hist);
    free(ncct->hist);
  }
  if(ncct->pty_master >= 0) close(ncct->pty_master);
  if(ncct->pty_slave >= 0) close(ncct->pty_slave);
  if(ncct->outbuf) free(ncct->outbuf);
  if(ncct->telnet) noit_console_telnet_free(ncct->telnet);
  noit_hash_destroy(&ncct->userdata, NULL, noit_console_userdata_free);
  while(ncct->state_stack) {
    noit_console_state_stack_t *tmp;
    tmp = ncct->state_stack;
    ncct->state_stack = tmp->last;
    if(tmp->name) free(tmp->name);
    free(tmp);
  }
  lf = noit_log_stream_find(ncct->feed_path);
  noit_log_stream_remove(ncct->feed_path);
  if(lf) {
    noit_log_stream_free(lf);
  }
  free(ncct);
}
예제 #10
0
static void *
asynch_logio_writer(void *vls) {
  noit_log_stream_t ls = vls;
  asynch_log_ctx *actx = ls->op_ctx;
  asynch_log_line *iter = NULL;
  int gen;
  gen = noit_atomic_inc32(&actx->gen);
  noitL(noit_debug, "starting asynchronous %s writer[%d/%p]\n",
        actx->name, (int)getpid(), (void *)(vpsized_int)pthread_self());
  while(gen == actx->gen) {
    pthread_rwlock_t *lock;
    int fast = 0, max = 1000;
    asynch_log_line *line;
    lock = ls->lock;
    if(lock) pthread_rwlock_rdlock(lock);
    while(max > 0 && NULL != (line = asynch_log_pop(actx, &iter))) {
      if(actx->write(actx, line) == -1) abort();
      if(line->buf_dynamic != NULL) free(line->buf_dynamic);
      free(line);
      fast = 1;
      max--;
    }
    if(lock) pthread_rwlock_unlock(lock);
    if(max > 0) {
      /* we didn't hit our limit... so we ran the queue dry */
      /* 200ms if there was nothing, 10ms otherwise */
      usleep(fast ? 10000 : 200000);
    }
  }
  noitL(noit_debug, "stopping asynchronous %s writer[%d/%p]\n",
        actx->name, (int)getpid(), (void *)(vpsized_int)pthread_self());
  pthread_exit((void *)0);
}
예제 #11
0
static int ping_icmp_init(noit_module_t *self) {
  socklen_t on;
  struct protoent *proto;
  ping_icmp_data_t *data;

  data = malloc(sizeof(*data));
  data->in_flight = calloc(1, sizeof(*data->in_flight));
  data->ipv4_fd = data->ipv6_fd = -1;

  if ((proto = getprotobyname("icmp")) == NULL) {
    noitL(noit_error, "Couldn't find 'icmp' protocol\n");
    return -1;
  }

  data->ipv4_fd = socket(AF_INET, SOCK_RAW, proto->p_proto);
  if(data->ipv4_fd < 0) {
    noitL(noit_error, "ping_icmp: socket failed: %s\n",
          strerror(errno));
  }
  else {
    socklen_t slen = sizeof(on);
    if(getsockopt(data->ipv4_fd, SOL_SOCKET, SO_SNDBUF, &on, &slen) == 0) {
      while(on < (1 << 20)) {
        on <<= 1;
        if(setsockopt(data->ipv4_fd, SOL_SOCKET, SO_SNDBUF,
                      &on, sizeof(on)) != 0) {
          on >>= 1;
          break;
        }
      }
      noitL(noit_debug, "ping_icmp: send buffer set to %d\n", on);
    }
    else
예제 #12
0
static int noit_stomp_submit(iep_thread_driver_t *dr,
                             const char *payload, size_t payloadlen) {
  struct stomp_driver *driver = (struct stomp_driver *)dr;
  apr_pool_t *dummy;
  apr_status_t rc;
  stomp_frame out;

  if(apr_pool_create(&dummy, NULL) != APR_SUCCESS) return -1;

  out.command = "SEND";
  out.headers = apr_hash_make(dummy);
  if (driver->exchange)
    apr_hash_set(out.headers, "exchange",
                 APR_HASH_KEY_STRING, driver->exchange);

  apr_hash_set(out.headers, "destination",
               APR_HASH_KEY_STRING, driver->destination);
  apr_hash_set(out.headers, "ack", APR_HASH_KEY_STRING, "auto");
 
  out.body_length = -1;
  out.body = (char *)payload;
  rc = stomp_write(driver->connection, &out, dummy);
  if(rc != APR_SUCCESS) {
    noitL(noit_error, "STOMP send failed, disconnecting\n");
    if(driver->connection) stomp_disconnect(&driver->connection);
    driver->connection = NULL;
  }
  else noitL(noit_debug, "STOMP send succeeded\n");
  apr_pool_destroy(dummy);
  return (rc == APR_SUCCESS) ? 0 : -1;
}
예제 #13
0
static int
stratcon_datastore_journal_sync(eventer_t e, int mask, void *closure,
                                struct timeval *now) {
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  const char *k;
  int klen;
  void *vij;
  interim_journal_t *ij;
  syncset_t *syncset = closure;

  if((mask & EVENTER_ASYNCH) == EVENTER_ASYNCH) {
    if(syncset->completion) {
      eventer_add(syncset->completion);
      eventer_trigger(syncset->completion, EVENTER_READ | EVENTER_WRITE);
    }
    free(syncset);
    return 0;
  }
  if(!((mask & EVENTER_ASYNCH_WORK) == EVENTER_ASYNCH_WORK)) return 0;

  noitL(ds_deb, "Syncing journal sets...\n");
  if (syncset->ws) {
    while(noit_hash_next(syncset->ws, &iter, &k, &klen, &vij)) {
      char tmppath[PATH_MAX], id_str[32];
      int suffix_idx;
      ij = vij;
      noitL(ds_deb, "Syncing journal set [%s,%s,%s]\n",
            ij->remote_str, ij->remote_cn, ij->fqdn);
      strlcpy(tmppath, ij->filename, sizeof(tmppath));
      suffix_idx = strlen(ij->filename) - 4; /* . t m p */
      ij->filename[suffix_idx] = '\0';
      if(rename(tmppath, ij->filename) != 0) {
        if(errno == EEXIST) {
          unlink(ij->filename);
          if(rename(tmppath, ij->filename) != 0) goto rename_failed;
        }
        else {
         rename_failed:
          noitL(noit_error, "rename failed(%s): (%s->%s)\n", strerror(errno),
                tmppath, ij->filename);
          exit(-1);
        }
      }
      fsync(ij->fd);
      close(ij->fd);
      ij->fd = -1;
      snprintf(id_str, sizeof(id_str), "%d", ij->storagenode_id);
      stratcon_ingest(ij->filename, ij->remote_str,
                      ij->remote_cn, id_str);
    }
    noit_hash_destroy(syncset->ws, free, interim_journal_free);
    free(syncset->ws);
  }
  else {
    noitL(noit_error, "attempted to sync non-existing working set\n");
  }

  return 0;
}
예제 #14
0
int
noit_control_dispatch(eventer_t e, int mask, void *closure,
                      struct timeval *now) {
  u_int32_t cmd;
  int len = 0, callmask = mask;
  void *vdelegation_table;
  noit_hash_table *delegation_table = NULL;
  acceptor_closure_t *ac = closure;

  assert(ac->rlen >= 0);
  while(len >= 0 && ac->rlen < sizeof(cmd)) {
    len = e->opset->read(e->fd, ((char *)&cmd) + ac->rlen,
                         sizeof(cmd) - ac->rlen, &mask, e);
    if(len == -1 && errno == EAGAIN)
      return EVENTER_READ | EVENTER_EXCEPTION;

    if(len > 0) ac->rlen += len;
  }
  assert(ac->rlen >= 0 && ac->rlen <= sizeof(cmd));

  if(callmask & EVENTER_EXCEPTION || ac->rlen != sizeof(cmd)) {
    int newmask;
socket_error:
    /* Exceptions cause us to simply snip the connection */
    eventer_remove_fd(e->fd);
    e->opset->close(e->fd, &newmask, e);
    acceptor_closure_free(ac);
    return 0;
  }

  ac->cmd = ntohl(cmd);
  /* Lookup cmd and dispatch */
  if(noit_hash_retrieve(&listener_commands,
                        (char *)&ac->dispatch, sizeof(ac->dispatch),
                        (void **)&vdelegation_table)) {
    void *vfunc;
    delegation_table = (noit_hash_table *)vdelegation_table;
    if(noit_hash_retrieve(delegation_table,
                          (char *)&ac->cmd, sizeof(ac->cmd), &vfunc)) {
      e->callback = *((eventer_func_t *)vfunc);
      return e->callback(e, callmask, closure, now);
    }
    else {
    const char *event_name;
      noitL(noit_error, "listener (%s %p) has no command: 0x%08x\n",
            (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???",
            delegation_table, cmd);
    }
  }
  else {
    const char *event_name;
    noitL(noit_error, "No delegation table for listener (%s %p)\n",
          (event_name = eventer_name_for_callback(ac->dispatch))?event_name:"???",
          delegation_table);
  }
  goto socket_error;
}
예제 #15
0
파일: ip_acl.c 프로젝트: Kami/reconnoiter
static int
ip_acl_onload(noit_image_t *self) {
  int i, cnt;
  noit_conf_section_t *acl_c;
  ip_acl_module_id = noit_check_register_module("ip_acl");
  if(ip_acl_module_id < 0) return -1;

  acl_c = noit_conf_get_sections(NULL, "/noit/acls//acl", &cnt);
  if(acl_c) {
    for(i=0; i<cnt; i++) {
      char *name;
      int j, rcnt, arcnt = 0;
      noit_conf_section_t *rule_c;
      if(noit_conf_get_string(acl_c[i], "@name", &name)) {
        rule_c = noit_conf_get_sections(acl_c[i], "rule", &rcnt);
        if(rule_c) {
          btrie *acl = calloc(1, sizeof(*acl));
          for(j=0; j<rcnt; j++) {
            int mask = -1, rv;
            char dirstr[16] = "unspecified";
            char *cp, target[256] = "";
            union {
              struct in_addr addr4;
              struct in6_addr addr6;
            } a;

            noit_conf_get_stringbuf(rule_c[j], "self::node()", target, sizeof(target));
            if(NULL != (cp = strchr(target, '/'))) {
              *cp++ = '\0';
              mask = atoi(cp);
            }
            if(!noit_conf_get_stringbuf(rule_c[j], "@type", dirstr, sizeof(dirstr)) ||
               (strcmp(dirstr, "deny") && strcmp(dirstr, "allow"))) {
              noitL(noit_error, "Unknown acl rule type \"%s\" in acl \"%s\"\n",
                    dirstr, name);
            }
            else if(inet_pton(AF_INET, target, &a) == 1) {
              if(mask == -1) mask = 32;
              noit_add_route_ipv4(acl, &a.addr4, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR);
              arcnt++;
            }
            else if(inet_pton(AF_INET6, target, &a) == 1) {
              if(mask == -1) mask = 128;
              noit_add_route_ipv6(acl, &a.addr6, mask, strcmp(dirstr, "allow") ? DENY_PTR : ALLOW_PTR);
              arcnt++;
            }
          }
          noitL(noit_error, "ACL %s/%p -> %d/%d rules\n", name, acl, arcnt, rcnt);
          noit_hash_replace(&acls, name, strlen(name), acl, free, free_btrie);
          free(rule_c);
        }
      }
    }
    free(acl_c);
  }
  return 0;
}
예제 #16
0
void
noit_poller_make_causal_map() {
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  uuid_t key_id;
  int klen;
  void *vcheck;

  /* Cleanup any previous causal map */
  while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen,
                       &vcheck)) {
    noit_check_t *check = (noit_check_t *)vcheck;
    dep_list_t *dep;
    while((dep = check->causal_checks) != NULL) {
      check->causal_checks = dep->next;
      free(dep);
    }
  }

  memset(&iter, 0, sizeof(iter));
  /* Walk all checks and add check dependencies to their parents */
  while(noit_hash_next(&polls, &iter, (const char **)key_id, &klen,
                       &vcheck)) {
    noit_check_t *check = (noit_check_t *)vcheck, *parent;
    if(check->oncheck) {
      /* This service is causally triggered by another service */
      char fullcheck[1024];
      char *name = check->oncheck;
      char *target = NULL;

      noitL(noit_debug, "Searching for upstream trigger on %s\n", name);
      if((target = strchr(check->oncheck, '`')) != NULL) {
        strlcpy(fullcheck, check->oncheck, target - check->oncheck);
        name = target + 1;
        target = fullcheck;
      }
      else
       target = check->target;

      parent = noit_poller_lookup_by_name(target, name);
      if(!parent) {
        check->flags |= NP_DISABLED;
        noitL(noit_stderr, "Disabling check %s`%s, can't find oncheck %s`%s\n",
              check->target, check->name, target, name);
      }
      else {
        dep_list_t *dep;
        dep = malloc(sizeof(*dep));
        dep->check = check;
        dep->next = parent->causal_checks;
        parent->causal_checks = dep;
        noitL(noit_debug, "Causal map %s`%s --> %s`%s\n",
              parent->target, parent->name, check->target, check->name);
      }
    }
  }
}
예제 #17
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;
}
예제 #18
0
static int
noit_lua_module_onload(noit_image_t *i) {
  int rv;
  lua_State *L;
  lua_module_closure_t *lmc;

  noit_lua_init();

  lmc = noit_image_get_userdata(i);
  L = lmc->lua_state;
  lua_getglobal(L, "require");
  lua_pushstring(L, lmc->object);
  rv = lua_pcall(L, 1, 1, 0);
  if(rv) {
    int i;
    noitL(nlerr, "lua: %s.onload failed\n", lmc->object);
    i = lua_gettop(L);
    if(i>0) {
      if(lua_isstring(L, i)) {
        const char *err;
        size_t len;
        err = lua_tolstring(L, i, &len);
        noitL(nlerr, "lua: %s\n", err);
      }
    }
    lua_pop(L,i);
    return -1;
  }
  lua_pop(L, lua_gettop(L));

  noit_lua_pushmodule(L, lmc->object);
  if(lua_isnil(L, -1)) {
    lua_pop(L, 1);
    noitL(nlerr, "lua: no such object %s\n", lmc->object);
    return -1;
  }
  lua_getfield(L, -1, "onload");
  lua_remove(L, -2);
  if(!lua_isfunction(L, -1)) {
    lua_pop(L, 1);
    /* No onload */
    return 0;
  }
  noit_lua_setup_module(L, (noit_module_t *)i);
  lua_pcall(L, 1, 1, 0);
  if(lua_isnumber(L, -1)) {
    int rv;
    rv = lua_tointeger(L, -1);
    lua_pop(L, 1);
    return rv;
  }
  lua_pop(L,1);
  noitL(nlerr, "%s.onload must return a integer\n", lmc->object);
  return -1;
}
예제 #19
0
static int noitice_hup(eventer_t e, int mask, void *unused, struct timeval *now) {
  if(__reload_needed) {
    noitL(noit_error, "SIGHUP received, performing reload\n");
    if(noit_conf_load(config_file) == -1) {
      noitL(noit_error, "Cannot load config: '%s'\n", config_file);
      exit(-1);
    }
    noit_poller_reload(NULL);
    __reload_needed = 0;
  }
  return 0;
}
예제 #20
0
void
noit_check_set_stats(struct _noit_module *module,
                     noit_check_t *check, stats_t *newstate) {
  int report_change = 0;
  dep_list_t *dep;
  if(check->stats.previous.status)
    free(check->stats.previous.status);
  noit_hash_destroy(&check->stats.previous.metrics, NULL, __free_metric);
  memcpy(&check->stats.previous, &check->stats.current, sizeof(stats_t));
  memcpy(&check->stats.current, newstate, sizeof(stats_t));
  if(check->stats.current.status)
    check->stats.current.status = strdup(check->stats.current.status);

  /* check for state changes */
  if(check->stats.current.available != NP_UNKNOWN &&
     check->stats.previous.available != NP_UNKNOWN &&
     check->stats.current.available != check->stats.previous.available)
    report_change = 1;
  if(check->stats.current.state != NP_UNKNOWN &&
     check->stats.previous.state != NP_UNKNOWN &&
     check->stats.current.state != check->stats.previous.state)
    report_change = 1;

  noitL(noit_debug, "%s`%s <- [%s]\n", check->target, check->name,
        check->stats.current.status);
  if(report_change) {
    noitL(noit_debug, "%s`%s -> [%s:%s]\n",
          check->target, check->name,
          noit_check_available_string(check->stats.current.available),
          noit_check_state_string(check->stats.current.state));
  }

  /* Write out our status */
  noit_check_log_status(check);
  /* Write out all metrics */
  noit_check_log_metrics(check);
  /* count the check as complete */
  check_completion_count++;

  for(dep = check->causal_checks; dep; dep = dep->next) {
    noit_module_t *mod;
    mod = noit_module_lookup(dep->check->module);
    assert(mod);
    noitL(noit_debug, "Firing %s`%s in response to %s`%s\n",
          dep->check->target, dep->check->name,
          check->target, check->name);
    if((dep->check->flags & NP_DISABLED) == 0)
      if(mod->initiate_check)
        mod->initiate_check(mod, dep->check, 1, check);
  }
}
void *
noit_livestream_thread_main(void *e_vptr) {
  int mask;
  eventer_t e = e_vptr;
  acceptor_closure_t *ac = e->closure;
  noit_livestream_closure_t *jcl = ac->service_ctx;

  /* Go into blocking mode */
  if(eventer_set_fd_blocking(e->fd) == -1) {
    noitL(noit_error, "failed setting livestream to blocking: [%d] [%s]\n",
          errno, strerror(errno));
    goto alldone;
  }

  while(1) {
    u_int32_t netlen;
    struct log_entry *le = NULL;
    int rv;
   
    sem_wait(&jcl->lqueue_sem);
    pthread_mutex_lock(&jcl->lqueue_lock);
    if(jcl->lqueue) {
      /* If there are items, pop and advance the header pointer */
      le = jcl->lqueue;
      jcl->lqueue = jcl->lqueue->next;
      if(!jcl->lqueue) jcl->lqueue_end = NULL;
    }
    pthread_mutex_unlock(&jcl->lqueue_lock);

    if(!le) continue;

    /* Here we actually push the message */
    netlen = htonl(le->len);
    if((rv = Ewrite(&netlen, sizeof(netlen))) != sizeof(netlen)) {
      noitL(noit_error, "Error writing le header over SSL %d != %d\n",
            rv, (int)sizeof(netlen));
      goto alldone;
    }
    if((rv = Ewrite(le->buff, le->len)) != le->len) {
      noitL(noit_error, "Error writing livestream message over SSL %d != %d\n",
            rv, le->len);
      goto alldone;
    }
  }

 alldone:
  e->opset->close(e->fd, &mask, e);
  jcl->wants_shutdown = 1;
  if(ac) acceptor_closure_free(ac);
  return NULL;
}
예제 #22
0
static int noit_rabbimq_connect(iep_thread_driver_t *dr) {
  struct amqp_driver *driver = (struct amqp_driver *)dr;

  if(!driver->connection) {
    int sidx = driver->nconnects++ % driver->nhosts;
    struct timeval timeout;
    amqp_rpc_reply_t r, *rptr;

    noitL(noit_error, "AMQP connect: %s:%d\n",
          driver->hostname[sidx], driver->port);
    BUMPSTAT(connects);
    driver->hostidx = sidx;
    timeout.tv_sec = driver->heartbeat;
    timeout.tv_usec = 0;
    driver->sockfd = amqp_open_socket(driver->hostname[sidx], driver->port, &timeout);
    if(driver->sockfd < 0) {
      noitL(noit_error, "AMQP connect failed: %s:%d\n",
            driver->hostname[sidx], driver->port);
      return -1;
    }
    driver->has_error = 0;
    driver->connection = amqp_new_connection();
    amqp_set_basic_return_cb(driver->connection, noit_rabbitmq_brcb, driver);
    amqp_set_sockfd(driver->connection, driver->sockfd);
    r = amqp_login(driver->connection,
                   driver->vhost, 0, 131072, driver->heartbeat,
                   AMQP_SASL_METHOD_PLAIN,
                   driver->username, driver->password);
    if(r.reply_type != AMQP_RESPONSE_NORMAL) {
      noitL(noit_error, "AMQP login failed\n");
      amqp_connection_close(driver->connection, AMQP_REPLY_SUCCESS);
      amqp_destroy_connection(driver->connection);
      driver->connection = NULL;
      return -1;
    }

    amqp_channel_open(driver->connection, 1);
    rptr = amqp_get_rpc_reply();
    if(rptr->reply_type != AMQP_RESPONSE_NORMAL) {
      noitL(noit_error, "AMQP channe_open failed\n");
      amqp_connection_close(driver->connection, AMQP_REPLY_SUCCESS);
      amqp_destroy_connection(driver->connection);
      driver->connection = NULL;
      return -1;
    }
    gettimeofday(&driver->last_hb, NULL);
    return 0;
  }
  /* 1 means already connected */
  return 1;
}
예제 #23
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;
}
예제 #24
0
static void eventer_kqueue_impl_update(eventer_t e, int mask) {
  if(e->mask & EVENTER_TIMER) {
    eventer_update_timed(e, mask);
    return;
  }
  noitL(eventer_deb, "kqueue: update(%d, %x->%x)\n", e->fd, e->mask, mask);
  /* Disable old, if they aren't active in the new */
  if((e->mask & (EVENTER_READ | EVENTER_EXCEPTION)) &&
     !(mask & (EVENTER_READ | EVENTER_EXCEPTION)))
    ke_change(e->fd, EVFILT_READ, EV_DELETE | EV_DISABLE, e);
  if((e->mask & (EVENTER_WRITE)) &&
     !(mask & (EVENTER_WRITE)))
    ke_change(e->fd, EVFILT_WRITE, EV_DELETE | EV_DISABLE, e);

  /* Enable new, if the weren't in the old */
  if((mask & (EVENTER_READ | EVENTER_EXCEPTION)) &&
     !(e->mask & (EVENTER_READ | EVENTER_EXCEPTION)))
    ke_change(e->fd, EVFILT_READ, EV_ADD | EV_ENABLE, e);
  if((mask & (EVENTER_WRITE)) &&
     !(e->mask & (EVENTER_WRITE)))
    ke_change(e->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, e);

  /* Switch */
  e->mask = mask;
}
예제 #25
0
static int
check_test_sweeper(eventer_t e, int mask, void *closure,
                   struct timeval *now) {
  int left = 0;
  noit_skiplist_node *iter = NULL;
  sweeper_event = NULL;
  iter = noit_skiplist_getlist(&in_progress);
  while(iter) {
    struct check_test_closure *cl = iter->data;
    /* advance here, we might delete */
    noit_skiplist_next(&in_progress,&iter);
    if(NOIT_CHECK_DISABLED(cl->check)) {
      if(NOIT_CHECK_SHOULD_RESOLVE(cl->check))
        noit_check_resolve(cl->check);
      if(NOIT_CHECK_RESOLVED(cl->check)) {
        noit_module_t *m = noit_module_lookup(cl->check->module);
        cl->check->flags &= ~NP_DISABLED;
        if(NOIT_CHECK_SHOULD_RESOLVE(cl->check))
          noitL(nldeb, "translated to %s\n", cl->check->target_ip);
        if(m) m->initiate_check(m, cl->check, 1, NULL);
      }
      left++;
    }
    else if(NOIT_CHECK_RUNNING(cl->check)) left++;
    else
      noit_skiplist_remove(&in_progress, cl->restc,
                           (noit_freefunc_t)rest_test_check_result);
  }

  if(left) check_test_schedule_sweeper();
  return 0;
}
예제 #26
0
static int
lua_general_resume(noit_lua_resume_info_t *ri, int nargs) {
  const char *err = NULL;
  int status, base, rv = 0;

#if LUA_VERSION_NUM >= 502
  status = lua_resume(ri->coro_state, ri->lmc->lua_state, nargs);
#else
  status = lua_resume(ri->coro_state, nargs);
#endif

  switch(status) {
    case 0: break;
    case LUA_YIELD:
      lua_gc(ri->coro_state, LUA_GCCOLLECT, 0);
      return 0;
    default: /* The complicated case */
      base = lua_gettop(ri->coro_state);
      if(base>=0) {
        if(lua_isstring(ri->coro_state, base-1)) {
          err = lua_tostring(ri->coro_state, base-1);
          noitL(nlerr, "err -> %s\n", err);
        }
      }
      rv = -1;
  }

  lua_general_ctx_free(ri);
  return rv;
}
static int
rest_stream_data(noit_http_rest_closure_t *restc,
                 int npats, char **pats) {
  /* We're here and want to subvert the rest system */
  const char *document_domain = NULL;
  noit_http_session_ctx *ctx = restc->http_ctx;
  noit_http_connection *conn = noit_http_session_connection(ctx);
  eventer_t e;
  acceptor_closure_t *ac = restc->ac;

  /* Rewire the handler */
  if(ac->service_ctx_free)
    ac->service_ctx_free(ac->service_ctx);
  ac->service_ctx = ctx;
  ac->service_ctx_free = noit_http_ctx_acceptor_free;

  if(!noit_hash_retr_str(ac->config,
                         "document_domain", strlen("document_domain"),
                         &document_domain)) {
    noitL(noit_error, "Document domain not set!  Realtime streaming will be broken\n");
    document_domain = "";
  }

  noit_http_process_querystring(noit_http_session_request(ctx));
  /* Rewire the http context */
  e = noit_http_connection_event(conn);
  e->callback = stratcon_realtime_http_handler;
  noit_http_session_set_dispatcher(ctx, stratcon_request_dispatcher,
                                   alloc_realtime_context(document_domain));
  return stratcon_request_dispatcher(ctx);
}
예제 #28
0
static void
ke_change (register int const ident,
           register int const filter,
           register int const flags,
           register eventer_t e) {
  register struct kevent *kep;
  KQUEUE_DECL;
  KQUEUE_SETUP;
  if(!kqs) kqs = master_kqs;

  if(kqs == master_kqs) pthread_mutex_lock(&kqs_lock);
  if (!ke_vec_a) {
    kqs_init(kqs);
  }
  else if (ke_vec_used == ke_vec_a) {
    ke_vec_a <<= 1;
    ke_vec = (struct kevent *) realloc(ke_vec,
                                       ke_vec_a * sizeof (struct kevent));
  }
  kep = &ke_vec[ke_vec_used++];

  EV_SET(kep, ident, filter, flags, 0, 0, (void *)(vpsized_int)e->fd);
  noitL(eventer_deb, "debug: ke_change(fd:%d, filt:%x, flags:%x)\n",
        ident, filter, flags);
  if(kqs == master_kqs) pthread_mutex_unlock(&kqs_lock);
}
예제 #29
0
static void
stratcon_ingest_sweep_journals_int(char *first, char *second, char *third,
                                   int (*test)(const char *),
                                   int (*ingest)(const char *fullpath,
                                                 const char *remote_str,
                                                 const char *remote_cn,
                                                 const char *id_str)) {
  char path[PATH_MAX];
  DIR *root;
  struct dirent *de, *entry;
  int i = 0, cnt = 0;
  char **entries;
  int size = 0;

  snprintf(path, sizeof(path), "%s%s%s%s%s%s%s", basejpath,
           first ? "/" : "", first ? first : "",
           second ? "/" : "", second ? second : "",
           third ? "/" : "", third ? third : "");
#ifdef _PC_NAME_MAX
  size = pathconf(path, _PC_NAME_MAX);
#endif
  size = MAX(size, PATH_MAX + 128);
  de = alloca(size);
  root = opendir(path);
  if(!root) return;
  while(portable_readdir_r(root, de, &entry) == 0 && entry != NULL) cnt++;
  closedir(root);
  root = opendir(path);
  if(!root) return;
  entries = malloc(sizeof(*entries) * cnt);
  while(portable_readdir_r(root, de, &entry) == 0 && entry != NULL) {
    if(i < cnt) {
      entries[i++] = strdup(entry->d_name);
    }
  }
  closedir(root);
  cnt = i; /* could have changed, directories are fickle */
  qsort(entries, i, sizeof(*entries),
        (int (*)(const void *, const void *))strcasecmp);
  for(i=0; i<cnt; i++) {
    if(!strcmp(entries[i], ".") || !strcmp(entries[i], "..")) continue;
    noitL(ds_deb, "Processing L%d entry '%s'\n",
          third ? 4 : second ? 3 : first ? 2 : 1, entries[i]);
    if(!first)
      stratcon_ingest_sweep_journals_int(entries[i], NULL, NULL, test, ingest);
    else if(!second)
      stratcon_ingest_sweep_journals_int(first, entries[i], NULL, test, ingest);
    else if(!third)
      stratcon_ingest_sweep_journals_int(first, second, entries[i], test, ingest);
    else if(test(entries[i])) {
      char fullpath[PATH_MAX];
      snprintf(fullpath, sizeof(fullpath), "%s/%s/%s/%s/%s", basejpath,
               first,second,third,entries[i]);
      ingest(fullpath,first,second,third);
    }
  }
  for(i=0; i<cnt; i++)
    free(entries[i]);
  free(entries);
}
예제 #30
0
int
allocate_pty(int *master, int *slave) {
#if defined(HAVE_OPENPTY) || (defined(HAVE_DECL_OPENPTY) && HAVE_DECL_OPENPTY != 0)
  if(openpty(master, slave, NULL, NULL, NULL)) return -1;
#else
  /* STREAMS... sigh */
  char   *slavename;
  extern char *ptsname();

  *master = open("/dev/ptmx", O_RDWR);  /* open master */
  if(*master < 0) return -1;
  grantpt(*master);                     /* change permission of   slave */
  unlockpt(*master);                    /* unlock slave */
  slavename = ptsname(*master);         /* get name of slave */
  *slave = open(slavename, O_RDWR);    /* open slave */
  if(*slave < 0) {
    close(*master);
    *master = -1;
    return -1;
  }
  /* This is a bit backwards as we using the PTY backwards.
   * We want to make the master a tty instead of the slave... odd, I know.
   */
  ioctl(*master, I_PUSH, "ptem");       /* push ptem */
  ioctl(*master, I_PUSH, "ldterm");     /* push ldterm*/
#endif
  if(eventer_set_fd_nonblocking(*master)) return -1;
  noitL(noit_debug, "allocate_pty -> %d,%d\n", *master, *slave);
  return 0;
}