Esempio n. 1
0
static int noit_lua_dns_lookup(lua_State *L) {
  dns_lookup_ctx_t *dlc, **holder;
  const char *c, *query = "", *ctype = "IN", *rtype = "A";
  char *ctype_up, *rtype_up, *d;
  void *vnv_pair;
  noit_lua_check_info_t *ci;

  ci = get_ci(L);
  assert(ci);

  holder = (dns_lookup_ctx_t **)lua_touserdata(L, lua_upvalueindex(1));
  if(holder != lua_touserdata(L,1))
    luaL_error(L, "Must be called as method\n");
  dlc = *holder;

  if(lua_gettop(L) > 1) query = lua_tostring(L, 2);
  if(lua_gettop(L) > 2) rtype = lua_tostring(L, 3);
  if(lua_gettop(L) > 3) ctype = lua_tostring(L, 4);

  ctype_up = alloca(strlen(ctype)+1);
  for(d = ctype_up, c = ctype; *c; d++, c++) *d = toupper(*c);
  *d = '\0';
  rtype_up = alloca(strlen(rtype)+1);
  for(d = rtype_up, c = rtype; *c; d++, c++) *d = toupper(*c);
  *d = '\0';

  if(!noit_hash_retrieve(&dns_ctypes, ctype_up, strlen(ctype_up), &vnv_pair))
    dlc->error = strdup("bad class");
  else
    dlc->query_ctype = ((struct dns_nameval *)vnv_pair)->val;

  if(!noit_hash_retrieve(&dns_rtypes, rtype_up, strlen(rtype_up), &vnv_pair)) 
    dlc->error = strdup("bad rr type");
  else
    dlc->query_rtype = ((struct dns_nameval *)vnv_pair)->val;

  dlc->active = 1;
  noit_atomic_inc32(&dlc->refcnt);
  if(!dlc->error) {
    int abs;
    if(!dns_ptodn(query, strlen(query), dlc->dn, sizeof(dlc->dn), &abs) ||
       !dns_submit_dn(dlc->h->ctx, dlc->dn, dlc->query_ctype, dlc->query_rtype,
                      abs | DNS_NOSRCH, NULL, dns_cb, dlc)) {
      dlc->error = strdup("submission error");
      noit_atomic_dec32(&dlc->refcnt);
    }
    else {
      struct timeval now;
      gettimeofday(&now, NULL);
      dns_timeouts(dlc->h->ctx, -1, now.tv_sec);
    }
  }
  if(dlc->error) {
    dlc->active = 0;
    luaL_error(L, "dns: %s\n", dlc->error);
  }
  return noit_lua_yield(ci, 0);
}
Esempio n. 2
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;
}
Esempio n. 3
0
noit_check_t *
noit_check_clone(uuid_t in) {
  noit_check_t *checker, *new_check;
  void *vcheck;
  if(noit_hash_retrieve(&polls,
                        (char *)in, UUID_SIZE,
                        &vcheck) == 0) {
    return NULL;
  }
  checker = (noit_check_t *)vcheck;
  if(checker->oncheck) {
    return NULL;
  }
  new_check = calloc(1, sizeof(*new_check));
  memcpy(new_check, checker, sizeof(*new_check));
  new_check->target = strdup(new_check->target);
  new_check->module = strdup(new_check->module);
  new_check->name = strdup(new_check->name);
  new_check->filterset = strdup(new_check->filterset);
  new_check->flags = 0;
  new_check->fire_event = NULL;
  memset(&new_check->last_fire_time, 0, sizeof(new_check->last_fire_time));
  memset(&new_check->stats, 0, sizeof(new_check->stats));
  new_check->closure = NULL;
  new_check->config = calloc(1, sizeof(*new_check->config));
  noit_hash_merge_as_dict(new_check->config, checker->config);
  return new_check;
}
Esempio n. 4
0
void
noit_control_dispatch_delegate(eventer_func_t listener_dispatch,
                               u_int32_t cmd,
                               eventer_func_t delegate_dispatch) {
  u_int32_t *cmd_copy;
  eventer_func_t *handler_copy;
  void *vdelegation_table;
  noit_hash_table *delegation_table;
  if(!noit_hash_retrieve(&listener_commands,
                         (char *)&listener_dispatch, sizeof(listener_dispatch),
                         &vdelegation_table)) {
    delegation_table = calloc(1, sizeof(*delegation_table));
    handler_copy = malloc(sizeof(*handler_copy));
    *handler_copy = listener_dispatch;
    noit_hash_store(&listener_commands,
                    (char *)handler_copy, sizeof(*handler_copy),
                    delegation_table);
  }
  else
    delegation_table = (noit_hash_table *)vdelegation_table;

  cmd_copy = malloc(sizeof(*cmd_copy));
  *cmd_copy = cmd;
  handler_copy = malloc(sizeof(*handler_copy));
  *handler_copy = delegate_dispatch;
  noit_hash_replace(delegation_table,
                    (char *)cmd_copy, sizeof(*cmd_copy),
                    handler_copy,
                    free, free);
}
Esempio n. 5
0
noit_boolean
noit_apply_filterset(const char *filterset,
                     noit_check_t *check,
                     metric_t *metric) {
  /* We pass in filterset here just in case someone wants to apply
   * a filterset other than check->filterset.. You never know.
   */
  void *vfs;
  if(!filterset) return noit_true;   /* No filter */
  if(!filtersets) return noit_false; /* Couldn't possibly match */

  LOCKFS();
  if(noit_hash_retrieve(filtersets, filterset, strlen(filterset), &vfs)) {
    filterset_t *fs = (filterset_t *)vfs;
    filterrule_t *r;
    noit_atomic_inc32(&fs->ref_cnt);
    UNLOCKFS();
#define MATCHES(rname, value) noit_apply_filterrule(r->rname, r->rname##_e, value)
    for(r = fs->rules; r; r = r->next) {
      if(MATCHES(target, check->target) &&
         MATCHES(module, check->module) &&
         MATCHES(name, check->name) &&
         MATCHES(metric, metric->metric_name))
        return (r->type == NOIT_FILTER_ACCEPT) ? noit_true : noit_false;
    }
    filterset_free(fs);
    return noit_false;
  }
  UNLOCKFS();
  return noit_false;
}
Esempio n. 6
0
static int
noit_config_check_update_attrs(xmlNodePtr node, int argc, char **argv) {
  int i, error = 0;
  if(argc % 2) return -1;

  for(i=0; i<argc; i+=2) {
    void *vattrinfo;
    struct _valid_attr_t *attrinfo;
    char *attr = argv[i], *val = NULL;
    if(!strcasecmp(argv[i], "no")) attr = argv[i+1];
    else val = argv[i+1];
    if(!noit_hash_retrieve(&check_attrs, attr, strlen(attr),
                           &vattrinfo)) {
      error = 1;
      break;
    }
    attrinfo = vattrinfo;
    /* The fixation stuff doesn't matter here, this check is brand-new */
    xmlUnsetProp(node, (xmlChar *)attrinfo->name);
    if(val)
      xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)val);
    noit_conf_mark_changed();
  }
  return error;
}
Esempio n. 7
0
noit_log_stream_t
noit_log_stream_new(const char *name, const char *type, const char *path,
                    void *ctx, noit_hash_table *config) {
  noit_log_stream_t ls, saved;
  struct _noit_log_stream tmpbuf;
  void *vops = NULL;

  ls = calloc(1, sizeof(*ls));
  ls->name = strdup(name);
  ls->path = path ? strdup(path) : NULL;
  ls->type = type ? strdup(type) : NULL;
  ls->enabled = 1;
  ls->config = config;
  if(!type)
    ls->ops = NULL;
  else if(noit_hash_retrieve(&noit_logops, type, strlen(type),
                             &vops))
    ls->ops = vops;
  else
    goto freebail;
 
  if(ls->ops && ls->ops->openop(ls)) goto freebail;

  saved = noit_log_stream_find(name);
  if(saved) {
    pthread_rwlock_t *lock = saved->lock;
    memcpy(&tmpbuf, saved, sizeof(*saved));
    memcpy(saved, ls, sizeof(*saved));
    memcpy(ls, &tmpbuf, sizeof(*saved));
    saved->lock = lock;

    ls->lock = NULL;
    noit_log_stream_free(ls);
    ls = saved;
  }
  else {
    /* We strdup the name *again*.  We'going to kansas city shuffle the
     * ls later (see memcpy above).  However, if don't strdup, then the
     * noit_log_stream_free up there will sweep our key right our from
     * under us.
     */
    if(noit_hash_store(&noit_loggers,
                       strdup(ls->name), strlen(ls->name), ls) == 0)
      goto freebail;
    ls->lock = calloc(1, sizeof(*ls->lock));
    noit_log_init_rwlock(ls);
  }
  /* This is for things that don't open on paths */
  if(ctx) ls->op_ctx = ctx;
  return ls;

 freebail:
  fprintf(stderr, "Failed to instantiate logger(%s,%s,%s)\n",
          name, type ? type : "[null]", path ? path : "[null]");
  free(ls->name);
  if(ls->path) free(ls->path);
  if(ls->type) free(ls->type);
  free(ls);
  return NULL;
}
Esempio n. 8
0
noit_check_t *
noit_poller_lookup(uuid_t in) {
  void *vcheck;
  if(noit_hash_retrieve(&polls, (char *)in, UUID_SIZE, &vcheck))
    return (noit_check_t *)vcheck;
  return NULL;
}
Esempio n. 9
0
noit_log_stream_t
noit_log_stream_find(const char *name) {
  void *vls;
  if(noit_hash_retrieve(&noit_loggers, name, strlen(name), &vls)) {
    return (noit_log_stream_t)vls;
  }
  return NULL;
}
Esempio n. 10
0
void *
noit_console_userdata_get(struct __noit_console_closure *ncct,
                          const char *name) {
  void *vitem;
  if(noit_hash_retrieve(&ncct->userdata, name, strlen(name),
                        &vitem))
    return ((noit_console_userdata_t *)vitem)->data;
  return NULL;
}
Esempio n. 11
0
static int __isactive_ci(struct dns_check_info *ci) {
  void *u;
  int exists = 0;
  pthread_mutex_lock(&active_events_lock);
  if(noit_hash_retrieve(&active_events, (void *)&ci, sizeof(ci), &u))
    exists = 1;
  pthread_mutex_unlock(&active_events_lock);
  return exists;
}
Esempio n. 12
0
int
noit_filter_exists(const char *name) {
  int exists;
  void *v;
  LOCKFS();
  exists = noit_hash_retrieve(filtersets, name, strlen(name), &v);
  UNLOCKFS();
  return exists;
}
Esempio n. 13
0
jlog_feed_stats_t *
noit_jlog_feed_stats(const char *sub) {
  void *vs = NULL;
  jlog_feed_stats_t *s = NULL;
  if(noit_hash_retrieve(&feed_stats, sub, strlen(sub), &vs))
    return (jlog_feed_stats_t *)vs;
  s = calloc(1, sizeof(*s));
  s->feed_name = strdup(sub);
  noit_hash_store(&feed_stats, s->feed_name, strlen(s->feed_name), s);
  return s;
}
Esempio n. 14
0
static rest_request_handler
noit_http_get_handler(noit_http_rest_closure_t *restc) {
  struct rule_container *cont = NULL;
  struct rest_url_dispatcher *rule;
  noit_http_request *req = noit_http_session_request(restc->http_ctx);
  const char *uri_str;
  const char *eoq, *eob;
  uri_str = noit_http_request_uri_str(req);
  eoq = strchr(uri_str, '?');
  if(!eoq)
    eoq = uri_str + strlen(uri_str);
  eob = eoq - 1;

  /* find the right base */
  while(1) {
    void *vcont;
    while(eob >= uri_str && *eob != '/') eob--;
    if(eob < uri_str) break; /* off the front */
    if(noit_hash_retrieve(&dispatch_points, uri_str,
                          eob - uri_str + 1, &vcont)) {
      cont = vcont;
      eob++; /* move past the determined base */
      break;
    }
    eob--;
  }
  if(!cont) return NULL;
  for(rule = cont->rules; rule; rule = rule->next) {
    int ovector[30];
    int cnt;
    if(strcmp(rule->method, noit_http_request_method_str(req))) continue;
    if((cnt = pcre_exec(rule->expression, rule->extra, eob, eoq - eob, 0, 0,
                        ovector, sizeof(ovector)/sizeof(*ovector))) > 0) {
      /* We match, set 'er up */
      restc->fastpath = rule->handler;
      restc->nparams = cnt - 1;
      if(restc->nparams) {
        restc->params = calloc(restc->nparams, sizeof(*restc->params));
        for(cnt = 0; cnt < restc->nparams; cnt++) {
          int start = ovector[(cnt+1)*2];
          int end = ovector[(cnt+1)*2+1];
          restc->params[cnt] = malloc(end - start + 1);
          memcpy(restc->params[cnt], eob + start, end - start);
          restc->params[cnt][end - start] = '\0';
        }
      }
      if(rule->auth && !rule->auth(restc, restc->nparams, restc->params))
        return noit_http_rest_permission_denied;
      return restc->fastpath;
    }
  }
  return NULL;
}
Esempio n. 15
0
static dns_ctx_handle_t *dns_ctx_alloc(const char *ns, int port) {
  void *vh;
  dns_ctx_handle_t *h = NULL;
  pthread_mutex_lock(&dns_ctx_store_lock);
  if(ns == NULL && default_ctx_handle != NULL) {
    /* special case -- default context */
    h = default_ctx_handle;
    noit_atomic_inc32(&h->refcnt);
    goto bail;
  }
  if(ns &&
     noit_hash_retrieve(&dns_ctx_store, ns, strlen(ns), &vh)) {
    h = (dns_ctx_handle_t *)vh;
    noit_atomic_inc32(&h->refcnt);
  }
  else {
    int failed = 0;
    h = calloc(1, sizeof(*h));
    h->ns = ns ? strdup(ns) : NULL;
    h->ctx = dns_new(NULL);
    if(dns_init(h->ctx, 0) != 0) failed++;
    if(ns) {
      if(dns_add_serv(h->ctx, NULL) < 0) failed++;
      if(dns_add_serv(h->ctx, ns) < 0) failed++;
    }
    if(port && port != DNS_PORT) {
      dns_set_opt(h->ctx, DNS_OPT_PORT, port);
    }
    if(dns_open(h->ctx) < 0) failed++;
    if(failed) {
      noitL(nlerr, "dns_open failed\n");
      free(h->ns);
      free(h);
      h = NULL;
      goto bail;
    }
    dns_set_tmcbck(h->ctx, eventer_dns_utm_fn, h);
    h->e = eventer_alloc();
    h->e->mask = EVENTER_READ | EVENTER_EXCEPTION;
    h->e->closure = h;
    h->e->callback = dns_eventer_callback;
    h->e->fd = dns_sock(h->ctx);
    eventer_add(h->e);
    h->refcnt = 1;
    if(!ns)
      default_ctx_handle = h;
    else
      noit_hash_store(&dns_ctx_store, h->ns, strlen(h->ns), h);
  }
 bail:
  pthread_mutex_unlock(&dns_ctx_store_lock);
  return h;
}
Esempio n. 16
0
static noit_boolean
noit_apply_filterrule(noit_hash_table *m,
                      pcre *p, pcre_extra *pe, const char *subj) {
  int rc, ovector[30];
  if(m) {
    void *vptr;
    return noit_hash_retrieve(m, subj, strlen(subj), &vptr);
  }
  if(!p) return noit_true;
  rc = pcre_exec(p, pe, subj, strlen(subj), 0, 0, ovector, 30);
  if(rc >= 0) return noit_true;
  return noit_false;
}
Esempio n. 17
0
static noit_hash_table *
stratcon_datastore_journal_remove(struct sockaddr *remote,
                                  const char *remote_cn) {
  void *vhash = NULL;
  if(noit_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) {
    /* pluck it out */
    noit_hash_delete(&working_sets, remote_cn, strlen(remote_cn), free, NULL);
  }
  else {
    noitL(noit_error, "attempted checkpoint on non-existing workingset: '%s'\n",
          remote_cn);
  }
  return vhash;
}
Esempio n. 18
0
noit_lua_check_info_t *
get_ci(lua_State *L) {
  noit_lua_check_info_t *ci;
  lua_module_closure_t *lmc;
  void *v = NULL;
  if(noit_hash_retrieve(&noit_coros, (const char *)&L, sizeof(L), &v))
    return (noit_lua_check_info_t *)v;
  ci = calloc(1, sizeof(*ci));
  ci->coro_state = L;
  lua_getglobal(L, "noit_internal_lmc");;
  ci->lmc = lua_touserdata(L, lua_gettop(L));
  lua_pop(L, 1);
  noitL(noit_error, "lmc -> %p\n", ci->lmc);
  noit_hash_store(&noit_coros,
                  (const char *)&ci->coro_state, sizeof(ci->coro_state),
                  ci);
  return ci;
}
Esempio n. 19
0
int
noit_poller_deschedule(uuid_t in) {
  void *vcheck;
  noit_check_t *checker;
  if(noit_hash_retrieve(&polls,
                        (char *)in, UUID_SIZE,
                        &vcheck) == 0) {
    return -1;
  }
  checker = (noit_check_t *)vcheck;
  checker->flags |= (NP_DISABLED|NP_KILLED);

  noit_skiplist_remove(&polls_by_name, checker, NULL);
  noit_hash_delete(&polls, (char *)in, UUID_SIZE, NULL, NULL);

  noit_poller_free_check(checker);
  return 0;
}
Esempio n. 20
0
const char *eventer_name_for_callback_e(eventer_func_t f, eventer_t e) {
  void *vcd;
  struct callback_details *cd;
  if(noit_hash_retrieve(&__func_to_name, (char *)&f, sizeof(f), &vcd)) {
    cd = vcd;
    if(cd->functional_name && e) {
      char *buf;
      buf = pthread_getspecific(_tls_funcname_key);
      if(!buf) {
        buf = malloc(FUNCNAME_SIZE);
        pthread_setspecific(_tls_funcname_key, buf);
      }
      cd->functional_name(buf, FUNCNAME_SIZE, e, cd->closure);
      return buf;
    }
    return cd->simple_name;
  }
  return NULL;
}
Esempio n. 21
0
int
noit_http_rest_register_auth(const char *method, const char *base,
                             const char *expr, rest_request_handler f,
                             rest_authorize_func_t auth) {
  void *vcont;
  struct rule_container *cont;
  struct rest_url_dispatcher *rule;
  const char *error;
  int erroffset;
  pcre *pcre_expr;
  int blen = strlen(base);
  /* base must end in a /, 'cause I said so */
  if(blen == 0 || base[blen-1] != '/') return -1;
  pcre_expr = pcre_compile(expr, 0, &error, &erroffset, NULL);
  if(!pcre_expr) {
    noitL(noit_error, "Error in rest expr(%s) '%s'@%d: %s\n",
          base, expr, erroffset, error);
    return -1;
  }
  rule = calloc(1, sizeof(*rule));
  rule->method = strdup(method);
  rule->expression = pcre_expr;
  rule->extra = pcre_study(rule->expression, 0, &error);
  rule->handler = f;
  rule->auth = auth;

  /* Make sure we have a container */
  if(!noit_hash_retrieve(&dispatch_points, base, strlen(base), &vcont)) {
    cont = calloc(1, sizeof(*cont));
    cont->base = strdup(base);
    noit_hash_store(&dispatch_points, cont->base, strlen(cont->base), cont);
  }
  else cont = vcont;

  /* Append the rule */
  if(cont->rules_endptr) {
    cont->rules_endptr->next = rule;
    cont->rules_endptr = cont->rules_endptr->next;
  }
  else
    cont->rules = cont->rules_endptr = rule;
  return 0;
}
Esempio n. 22
0
static noit_hook_return_t
ip_acl_hook_impl(void *closure, noit_module_t *self,
                 noit_check_t *check, noit_check_t *cause) {
  char deny_msg[128];
  stats_t current;
  noit_hash_table *config;
  noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
  const char *k = NULL;
  int klen;
  void *data;
  config = noit_check_get_module_config(check, ip_acl_module_id);
  if(!config || config->size == 0) return NOIT_HOOK_CONTINUE;
  while(noit_hash_next(config, &iter, &k, &klen, &data)) {
    if(k) {
      void *dir = NULL;
      unsigned char mask;
      if(noit_hash_retrieve(&acls, k, strlen(k), &data)) {
        btrie *acl = data;
        if(check->target_family == AF_INET) {
          dir = noit_find_bpm_route_ipv4(acl, &check->target_addr.addr, &mask);
          if(dir == DENY_PTR) goto prevent;
          else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE;
        }
        else if(check->target_family == AF_INET6) {
          dir = noit_find_bpm_route_ipv6(acl, &check->target_addr.addr6, &mask);
          if(dir == DENY_PTR) goto prevent;
          else if(dir == ALLOW_PTR) return NOIT_HOOK_CONTINUE;
        }
      }
    }
  }
  return NOIT_HOOK_CONTINUE;

 prevent:
  memset(&current, 0, sizeof(current));
  current.available = NP_UNAVAILABLE;
  current.state = NP_BAD;
  gettimeofday(&current.whence, NULL);
  snprintf(deny_msg, sizeof(deny_msg), "prevented by ACL '%s'", k ? k : "unknown");
  current.status = deny_msg;
  noit_check_set_stats(check, &current);
  return NOIT_HOOK_DONE;
}
Esempio n. 23
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;
}
Esempio n. 24
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;
}
Esempio n. 25
0
static int
storage_node_quick_lookup(const char *uuid_str, const char *remote_cn,
                          int *sid_out, int *storagenode_id_out,
                          const char **remote_cn_out,
                          const char **fqdn_out, const char **dsn_out) {
  /* only called from the main thread -- no safety issues */
  void *vstr;
  const char *actual_remote_cn = NULL;
  if(remote_cn) actual_remote_cn = remote_cn;
  uuid_t id;
  uuid_parse((char *)uuid_str, id);
  if(noit_hash_retrieve(&uuid_map, (const char *)id, UUID_SIZE, &vstr)) {
    char *str = (char *)vstr;
    if(remote_cn && strcmp(str, remote_cn)) {
      /* replace with new remote */
      void *key = malloc(UUID_SIZE);
      memcpy(key, id, UUID_SIZE);
      actual_remote_cn = strdup(remote_cn);
      noit_hash_replace(&uuid_map, key, UUID_SIZE, (void *)actual_remote_cn,
                        free, free);
    }
  }
  else if(remote_cn) {
    void *key = malloc(UUID_SIZE);
    memcpy(key, id, UUID_SIZE);
    noit_hash_store(&uuid_map, key, UUID_SIZE, strdup(remote_cn));
  }
  if(!actual_remote_cn) actual_remote_cn = "[[null]]";

  if(sid_out) *sid_out = 0;
  if(storagenode_id_out) *storagenode_id_out = 0;
  if(remote_cn_out) *remote_cn_out = actual_remote_cn;
  if(fqdn_out) *fqdn_out = "";
  if(dsn_out) *dsn_out = "";
  return 0;
}
Esempio n. 26
0
static int dns_check_send(noit_module_t *self, noit_check_t *check,
                          noit_check_t *cause) {
  void *vnv_pair = NULL;
  struct dns_nameval *nv_pair;
  eventer_t newe;
  struct timeval p_int, now;
  struct dns_check_info *ci = check->closure;
  const char *config_val;
  const char *rtype = NULL;
  const char *nameserver = NULL;
  int port = 0;
  const char *port_str = NULL;
  const char *want_sort = NULL;
  const char *ctype = "IN";
  const char *query = NULL;
  char interpolated_nameserver[1024];
  char interpolated_query[1024];
  noit_hash_table check_attrs_hash = NOIT_HASH_EMPTY;

  BAIL_ON_RUNNING_CHECK(check);

  gettimeofday(&now, NULL);
  memcpy(&check->last_fire_time, &now, sizeof(now));
  ci->current.state = NP_BAD;
  ci->current.available = NP_UNAVAILABLE;
  ci->timed_out = 1;
  ci->nrr = 0;
  ci->sort = 1;

  if(!strcmp(check->name, "in-addr.arpa") ||
     (strlen(check->name) >= sizeof("::in-addr.arpa") - 1 &&
      !strcmp(check->name + strlen(check->name) - sizeof("::in-addr.arpa") + 1,
              "::in-addr.arpa"))) {
    /* in-addr.arpa defaults:
     *   nameserver to NULL
     *   rtype to PTR
     *   query to %[:inaddrarpa:target]
     */
    nameserver = NULL;
    rtype = "PTR";
    query = "%[:inaddrarpa:target_ip]";
  }
  else {
    nameserver = "%[target_ip]";
    rtype = "A";
    query = "%[name]";
  }

  if(noit_hash_retr_str(check->config, "port", strlen("port"),
                        &port_str)) {
    port = atoi(port_str);
  }

#define CONFIG_OVERRIDE(a) \
  if(noit_hash_retr_str(check->config, #a, strlen(#a), \
                        &config_val) && \
     strlen(config_val) > 0) \
    a = config_val
  CONFIG_OVERRIDE(ctype);
  CONFIG_OVERRIDE(nameserver);
  CONFIG_OVERRIDE(rtype);
  CONFIG_OVERRIDE(query);
  CONFIG_OVERRIDE(want_sort);
  if(nameserver && !strcmp(nameserver, "default")) nameserver = NULL;
  if(want_sort && strcasecmp(want_sort, "on") && strcasecmp(want_sort, "true"))
    ci->sort = 0;

  noit_check_make_attrs(check, &check_attrs_hash);

  if(nameserver) {
    noit_check_interpolate(interpolated_nameserver,
                           sizeof(interpolated_nameserver),
                           nameserver,
                           &check_attrs_hash, check->config);
    nameserver = interpolated_nameserver;
  }
  if(query) {
    noit_check_interpolate(interpolated_query,
                           sizeof(interpolated_query),
                           query,
                           &check_attrs_hash, check->config);
    query = interpolated_query;
  }
  noit_hash_destroy(&check_attrs_hash, NULL, NULL);

  check->flags |= NP_RUNNING;
  noitL(nldeb, "dns_check_send(%p,%s,%s,%s,%s,%s)\n",
        self, check->target, nameserver ? nameserver : "default",
        query ? query : "null", ctype, rtype);

  __activate_ci(ci);
  /* If this ci has a handle and it isn't the one we need,
   * we should release it
   */
  if(ci->h &&
     ((ci->h->ns == NULL && nameserver != NULL) ||
      (ci->h->ns != NULL && nameserver == NULL) ||
      (ci->h->ns && strcmp(ci->h->ns, nameserver)))) {
    dns_ctx_release(ci->h);
    ci->h = NULL;
  }
  /* use the cached one, unless we don't have one */
  if(!ci->h) ci->h = dns_ctx_alloc(nameserver, port);
  if(!ci->h) ci->error = strdup("bad nameserver");

  /* Lookup out class */
  if(!noit_hash_retrieve(&dns_ctypes, ctype, strlen(ctype),
                         &vnv_pair)) {
    if(ci->error) free(ci->error);
    ci->error = strdup("bad class");
  }
  else {
    nv_pair = (struct dns_nameval *)vnv_pair;
    ci->query_ctype = nv_pair->val;
  }
  /* Lookup out rr type */
  if(!noit_hash_retrieve(&dns_rtypes, rtype, strlen(rtype),
                         &vnv_pair)) {
    if(ci->error) free(ci->error);
    ci->error = strdup("bad rr type");
  }
  else {
    nv_pair = (struct dns_nameval *)vnv_pair;
    ci->query_rtype = nv_pair->val;
  }

  if(!ci->error) {
    /* Submit the query */
    int abs;
    if(!dns_ptodn(query, strlen(query), ci->dn, sizeof(ci->dn), &abs) ||
       !dns_submit_dn(ci->h->ctx, ci->dn, ci->query_ctype, ci->query_rtype,
                      abs | DNS_NOSRCH, NULL, dns_cb, ci)) {
      ci->error = strdup("submission error");
    }
    else {
      dns_timeouts(ci->h->ctx, -1, now.tv_sec);
    }
  }

  /* we could have completed by now... if so, we've nothing to do */

  if(!__isactive_ci(ci)) return 0;

  if(ci->error) {
    /* Errors here are easy, fail and avoid scheduling a timeout */
    ci->check->flags &= ~NP_RUNNING;
    dns_check_log_results(ci);
    __deactivate_ci(ci);
    return 0;
  }

  newe = eventer_alloc();
  newe->mask = EVENTER_TIMER;
  gettimeofday(&now, NULL);
  p_int.tv_sec = check->timeout / 1000;
  p_int.tv_usec = (check->timeout % 1000) * 1000;
  add_timeval(now, p_int, &newe->whence);
  newe->closure = ci;
  newe->callback = dns_check_timeout;
  ci->timeout_event = newe;
  eventer_add(newe);

  return 0;
}
Esempio n. 27
0
static int
noit_console_show_check(noit_console_closure_t ncct,
                        int argc, char **argv,
                        noit_console_state_t *state, void *closure) {
  int i, cnt;
  noit_conf_t_userdata_t *info;
  char xpath[1024];
  xmlXPathObjectPtr pobj = NULL;
  xmlXPathContextPtr xpath_ctxt = NULL;

  noit_conf_xml_xpath(NULL, &xpath_ctxt);
  if(argc > 1) {
    nc_printf(ncct, "requires zero or one arguments\n");
    return -1;
  }

  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA);
  /* We many not be in conf-t mode -- that's fine */
  if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info,
                                argc ? argv[0] : NULL)) {
    nc_printf(ncct, "could not find check '%s'\n", argv[0]);
    return -1;
  }

  pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt);
  if(!pobj || pobj->type != XPATH_NODESET ||
     xmlXPathNodeSetIsEmpty(pobj->nodesetval)) {
    nc_printf(ncct, "no checks found\n");
    goto out;
  }
  cnt = xmlXPathNodeSetGetLength(pobj->nodesetval);
  if(info && cnt != 1) {
    nc_printf(ncct, "Ambiguous check specified\n");
    goto out;
  }
  for(i=0; i<cnt; i++) {
    noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
    const char *k;
    int klen;
    void *data;
    uuid_t checkid;
    noit_check_t *check;
    noit_hash_table *config;
    xmlNodePtr node, anode, mnode = NULL;
    char *uuid_conf;
    char *module, *value;

    node = (noit_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i);
    uuid_conf = (char *)xmlGetProp(node, (xmlChar *)"uuid");
    if(!uuid_conf || uuid_parse(uuid_conf, checkid)) {
      nc_printf(ncct, "%s has invalid or missing UUID!\n",
                (char *)xmlGetNodePath(node) + strlen("/noit"));
      continue;
    }
    nc_printf(ncct, "==== %s ====\n", uuid_conf);

#define MYATTR(a,n,b) _noit_conf_get_string(node, &(n), "@" #a, &(b))
#define INHERIT(a,n,b) \
  _noit_conf_get_string(node, &(n), "ancestor-or-self::node()/@" #a, &(b))
#define SHOW_ATTR(a) do { \
  anode = NULL; \
  value = NULL; \
  INHERIT(a, anode, value); \
  nc_attr_show(ncct, #a, node, anode, value); \
} while(0)

    if(!INHERIT(module, mnode, module)) module = NULL;
    if(MYATTR(name, anode, value))
      nc_printf(ncct, " name: %s\n", value);
    else
      nc_printf(ncct, " name: %s [from module]\n", module ? module : "[undef]");
    nc_attr_show(ncct, "module", node, mnode, module);
    SHOW_ATTR(target);
    SHOW_ATTR(resolve_rtype);
    SHOW_ATTR(period);
    SHOW_ATTR(timeout);
    SHOW_ATTR(oncheck);
    SHOW_ATTR(filterset);
    SHOW_ATTR(disable);
    /* Print out all the config settings */
    config = noit_conf_get_hash(node, "config");
    while(noit_hash_next(config, &iter, &k, &klen, &data)) {
      nc_printf(ncct, " config::%s: %s\n", k, (const char *)data);
    }
    noit_hash_destroy(config, free, free);
    free(config);

    check = noit_poller_lookup(checkid);
    if(!check) {
      nc_printf(ncct, " ERROR: not in running system\n");
    }
    else {
      int idx = 0;
      nc_printf(ncct, " target_ip: %s\n", check->target_ip);
      nc_printf(ncct, " currently: ");
      if(NOIT_CHECK_RUNNING(check)) nc_printf(ncct, "%srunning", idx++?",":"");
      if(NOIT_CHECK_KILLED(check)) nc_printf(ncct, "%skilled", idx++?",":"");
      if(!NOIT_CHECK_CONFIGURED(check)) nc_printf(ncct, "%sunconfig", idx++?",":"");
      if(NOIT_CHECK_DISABLED(check)) nc_printf(ncct, "%sdisabled", idx++?",":"");
      if(!idx) nc_printf(ncct, "idle");
      nc_write(ncct, "\n", 1);
      if(check->stats.current.whence.tv_sec == 0) {
        nc_printf(ncct, " last run: never\n");
      }
      else {
        stats_t *c = &check->stats.current;
        int mcount=0;
        const char **sorted_keys;
        char buff[256];
        struct timeval now, diff;
        noit_boolean filtered;

        gettimeofday(&now, NULL);
        sub_timeval(now, c->whence, &diff);
        nc_printf(ncct, " last run: %0.3f seconds ago\n",
                  diff.tv_sec + (diff.tv_usec / 1000000.0));
        nc_printf(ncct, " availability/state: %s/%s\n",
                  noit_check_available_string(c->available),
                  noit_check_state_string(c->state));
        nc_printf(ncct, " status: %s\n", c->status ? c->status : "[[null]]");
        nc_printf(ncct, " metrics:\n");
        memset(&iter, 0, sizeof(iter));
        sorted_keys = alloca(c->metrics.size * sizeof(*sorted_keys));
        while(noit_hash_next(&c->metrics, &iter, &k, &klen, &data)) {
          if(sorted_keys) sorted_keys[mcount++] = k;
          else {
            noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data);
            filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data);
            nc_printf(ncct, "  %c%s\n", filtered ? '*' : ' ', buff);
          }
        }
        if(sorted_keys) {
          int j;
          qsort(sorted_keys, mcount, sizeof(*sorted_keys),
                _qsort_string_compare);
          for(j=0;j<mcount;j++) {
            if(noit_hash_retrieve(&c->metrics,
                                  sorted_keys[j], strlen(sorted_keys[j]),
                                  &data)) {
              noit_stats_snprint_metric(buff, sizeof(buff), (metric_t *)data);
              filtered = !noit_apply_filterset(check->filterset, check, (metric_t *)data);
              nc_printf(ncct, "  %c%s\n", filtered ? '*' : ' ', buff);
            }
          }
        }
      }
    }
  }
 out:
  if(pobj) xmlXPathFreeObject(pobj);
  return 0;
}
Esempio n. 28
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);
}
Esempio n. 29
0
static int
noit_console_filter_configure(noit_console_closure_t ncct,
                              int argc, char **argv,
                              noit_console_state_t *state,
                              void *closure) {
  xmlNodePtr parent, fsnode = NULL;
  int rv = -1;
  noit_conf_t_userdata_t *info;
  char xpath[1024];

  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA);
  if(!info) {
    nc_printf(ncct, "internal error\n");
    goto cleanup;
  }
  if(strncmp(info->path, "/filtersets/", strlen("/filtersets/")) &&
     strcmp(info->path, "/filtersets")) {
    nc_printf(ncct, "filterset only allows inside /filtersets (not %s)\n",
              info->path);
    goto cleanup;
  }
  if(argc != 1) {
    nc_printf(ncct, "filterset requires one argument\n");
    goto cleanup;
  }
  snprintf(xpath, sizeof(xpath), "/%s", info->path);
  parent = noit_conf_get_section(NULL, xpath);
  if(!parent) {
    nc_printf(ncct, "internal error, can't final current working path\n");
    goto cleanup;
  }
  snprintf(xpath, sizeof(xpath), "filterset[@name=\"%s\"]", argv[0]);
  fsnode = noit_conf_get_section(parent, xpath);
  if(closure) {
    int removed;
    removed = noit_filter_remove(fsnode);
    nc_printf(ncct, "%sremoved filterset '%s'\n",
              removed ? "" : "failed to ", argv[0]);
    if(removed) {
      xmlUnlinkNode(fsnode);
      xmlFreeNode(fsnode);
    }
    rv = !removed;
    goto cleanup;
  }
  if(!fsnode) {
    void *vfs;
    nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]);
    LOCKFS();
    if(noit_hash_retrieve(filtersets, argv[0], strlen(argv[0]), &vfs)) {
      UNLOCKFS();
      nc_printf(ncct, "filter of the same name already exists\n");
      goto cleanup;
    }
    UNLOCKFS();
    /* Fine the parent path */
    fsnode = xmlNewNode(NULL, (xmlChar *)"filterset");
    xmlSetProp(fsnode, (xmlChar *)"name", (xmlChar *)argv[0]);
    xmlAddChild(parent, fsnode);
    nc_printf(ncct, "created new filterset\n");
  }

  if(info) {
    char *xmlpath = NULL;
    if(info->path) free(info->path);
    xmlpath = (char *)xmlGetNodePath(fsnode);
    info->path = strdup(xmlpath + strlen("/noit"));
    free(xmlpath);
    strlcpy(info->filter_name, argv[0], sizeof(info->filter_name));
    if(state) {
      noit_console_state_push_state(ncct, state);
      noit_console_state_init(ncct);
    }
  }
 cleanup:
  return rv;
}
Esempio n. 30
0
static interim_journal_t *
interim_journal_get(struct sockaddr *remote, const char *remote_cn_in,
                    int storagenode_id, const char *fqdn_in) {
  void *vhash, *vij;
  noit_hash_table *working_set;
  interim_journal_t *ij;
  struct timeval now;
  char jpath[PATH_MAX];
  char remote_str[128];
  const char *remote_cn = remote_cn_in ? remote_cn_in : "default";
  const char *fqdn = fqdn_in ? fqdn_in : "default";

  noit_convert_sockaddr_to_buff(remote_str, sizeof(remote_str), remote);
  if(!*remote_str) strlcpy(remote_str, "default", sizeof(remote_str));

  /* Lookup the working set */
  if(!noit_hash_retrieve(&working_sets, remote_cn, strlen(remote_cn), &vhash)) {
    working_set = calloc(1, sizeof(*working_set));
    noit_hash_store(&working_sets, strdup(remote_cn), strlen(remote_cn),
                    working_set);
  }
  else
    working_set = vhash;

  /* Lookup the interim journal within the working set */
  if(!noit_hash_retrieve(working_set, fqdn, strlen(fqdn), &vij)) {
    ij = calloc(1, sizeof(*ij));
    gettimeofday(&now, NULL);
    snprintf(jpath, sizeof(jpath), "%s/%s/%s/%d/%08x%08x.tmp",
             basejpath, remote_str, remote_cn, storagenode_id,
             (unsigned int)now.tv_sec, (unsigned int)now.tv_usec);
    ij->remote_str = strdup(remote_str);
    ij->remote_cn = strdup(remote_cn);
    ij->fqdn = fqdn_in ? strdup(fqdn_in) : NULL;
    ij->storagenode_id = storagenode_id;
    ij->filename = strdup(jpath);
    ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640);
    if(ij->fd < 0 && errno == ENOENT) {
      if(mkdir_for_file(ij->filename, 0750)) {
        noitL(noit_error, "Failed to create dir for '%s': %s\n",
              ij->filename, strerror(errno));
        exit(-1);
      }
      ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640);
    }
    if(ij->fd < 0 && errno == EEXIST) {
      /* This can only occur if we crash after before checkpointing */
      unlink(ij->filename);
      ij->fd = open(ij->filename, O_RDWR | O_CREAT | O_EXCL, 0640);
    }
    if(ij->fd < 0) {
      noitL(noit_error, "Failed to open interim journal '%s': %s\n",
            ij->filename, strerror(errno));
      exit(-1);
    }
    noit_hash_store(working_set, strdup(fqdn), strlen(fqdn), ij);
  }
  else
    ij = vij;

  return ij;
}