コード例 #1
0
ファイル: mtev_skiplist.c プロジェクト: postwait/libmtev
void mtev_skiplist_add_index(mtev_skiplist *sl,
                             mtev_skiplist_comparator_t comp,
                             mtev_skiplist_comparator_t compk) {
  mtev_skiplist_node *m = NULL;
  mtev_skiplist *ni;
  int icount=0;
  mtev_skiplist_find(sl->index, (void *)comp, &m);
  if(m) return; /* Index already there! */
  ni = (mtev_skiplist *)malloc(sizeof(mtev_skiplist));
  mtev_skiplisti_init(ni);
  mtev_skiplist_set_compare(ni, comp, compk);
  /* Build the new index... This can be expensive! */
  m = mtev_skiplist_insert(sl->index, ni);
  while(m->prev) m=m->prev, icount++;
  for(m=mtev_skiplist_getlist(sl); m; mtev_skiplist_next(sl, &m)) {
    int j=icount-1;
    mtev_skiplist_node *nsln;
    nsln = mtev_skiplist_insert(ni, m->data);
    /* skip from main index down list */
    while(j>0) m=m->nextindex, j--;
    /* insert this node in the indexlist after m */
    nsln->nextindex = m->nextindex;
    if(m->nextindex) m->nextindex->previndex = nsln;
    nsln->previndex = m;
    m->nextindex = nsln;
  } 
}
コード例 #2
0
static void blank_update_v6(dns_cache_node *n) {
  if(n->ip6) free(n->ip6);
  n->ip6 = NULL;
  n->ip6_cnt = 0;
  mtev_skiplist_remove(&nc_dns_cache, n->target, NULL);
  n->last_updated = time(NULL);
  if (n->lookup_inflight_v4) {
    n->ttl = DEFAULT_FAILED_TTL;
  }
  n->lookup_inflight_v6 = mtev_false;
  mtev_skiplist_insert(&nc_dns_cache, n);
}
コード例 #3
0
ファイル: check_test.c プロジェクト: aidancully/reconnoiter
static int
rest_test_check(mtev_http_rest_closure_t *restc,
                int npats, char **pats) {
  noit_check_t *tcheck;
  mtev_http_session_ctx *ctx = restc->http_ctx;
  int mask, complete = 0;
  int error_code = 500;
  const char *error = "internal error";
  xmlDocPtr indoc, doc = NULL;
  xmlNodePtr attr, config, root;

  indoc = rest_get_xml_upload(restc, &mask, &complete);
  if(!complete) return mask;
  if(indoc == NULL) {
    error = "xml parse error";
    goto error;
  }
  if(!noit_validate_check_rest_post(indoc, &attr, &config, &error))
    goto error;

  tcheck = noit_fire_check(attr, config, &error);
  if(tcheck) {
    /* push the check and the context into a queue to complete on */
    struct check_test_closure *cl;
    cl = calloc(1, sizeof(*cl));
    if(npats == 1 && !strcmp(pats[0], ".json"))
      cl->output = WANTS_JSON;
    cl->check = tcheck;
    cl->restc = restc;
    mtev_skiplist_insert(&in_progress, cl);
    check_test_schedule_sweeper();
    if(restc->call_closure_free)
      restc->call_closure_free(restc->call_closure);
    restc->call_closure_free = NULL;
    restc->call_closure = NULL;
    restc->fastpath = rest_test_check_err;
    goto cleanup;
  }

 error:
  mtev_http_response_standard(ctx, error_code, "ERROR", "text/xml");
  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
  xmlDocSetRootElement(doc, root);
  xmlNodeAddContent(root, (xmlChar *)error);
  mtev_http_response_xml(ctx, doc);
  mtev_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
コード例 #4
0
int external_proc_spawn(struct proc_state *ps) {
  int i, stdin_fd;
  char stdoutfile[PATH_MAX];
  char stderrfile[PATH_MAX];

  mtevL(nldeb, "About to spawn: (%s)\n", ps->path);
  strlcpy(stdoutfile, "/tmp/noitext.XXXXXX", PATH_MAX);
  ps->stdout_fd = mkstemp(stdoutfile);
  if(ps->stdout_fd < 0) goto prefork_fail;
  unlink(stdoutfile);
  strlcpy(stderrfile, "/tmp/noitext.XXXXXX", PATH_MAX);
  ps->stderr_fd = mkstemp(stderrfile);
  if(ps->stderr_fd < 0) goto prefork_fail;
  unlink(stderrfile);
  ps->pid = fork();
  if(ps->pid == -1) goto prefork_fail;

  /* Here.. fork has succeeded */
  if(ps->pid) {
    mtev_skiplist_insert(&active_procs, ps);
    return 0;
  }
  /* Run the process */
  stdin_fd = open("/dev/null", O_RDONLY);
  if(stdin_fd < 0) close(0);
  else dup2(stdin_fd, 0);
  dup2(ps->stdout_fd, 1);
  dup2(ps->stderr_fd, 2);
  /* Shut off everything but std{in,out,err} */
  for(i=3;i<256;i++) close(i);
  execve(ps->path, ps->argv, ps->envp);
  exit(-1);
 prefork_fail:
  ps->status = -1;
  mtev_skiplist_insert(&done_procs, ps);
  return -1;
}
コード例 #5
0
static void
noit_check_resolver_remind_internal(const char *target,
                                    mtev_boolean needs_lock) {
  dns_cache_node *n;
  if(!target) return;
  if(needs_lock) DCLOCK();
  n = mtev_skiplist_find(&nc_dns_cache, target, NULL);
  if(n != NULL) {
    n->last_needed = time(NULL);
    if(needs_lock) DCUNLOCK();
    return; 
  }
  n = calloc(1, sizeof(*n));
  n->target = strdup(target);
  n->last_needed = time(NULL);
  mtev_skiplist_insert(&nc_dns_cache, n);
  if(needs_lock) DCUNLOCK();
}
コード例 #6
0
static void process_siglist() {
  mtev_skiplist_node *iter = NULL;
  struct proc_state *ps;
  pid_t pid;
  while(1) {
    int status = 0;
    pid = waitpid(0, &status, WNOHANG);
    if(pid <= 0) break;
    ps = mtev_skiplist_find_compare(&active_procs, &pid, &iter, __proc_state_pid);
    mtevL((ps?nldeb:nlerr), "reaped pid %d (check: %lld) -> %x\n",
          pid, (long long int)(ps?ps->check_no:-1), status);
    if(ps) {
      int rv = mtev_skiplist_remove_compare(&active_procs, &ps->pid, NULL,  __proc_state_pid);
      if (!rv) {
        mtevL(noit_error, "error: couldn't remove PID %d from active_procs in external\n", ps->pid);
      }
      mtev_skiplist_insert(&done_procs, ps);
    }
  }
}
コード例 #7
0
ファイル: mtev_skiplist.c プロジェクト: postwait/libmtev
mtev_skiplist_node *mtev_skiplist_insert_compare(mtev_skiplist *sl,
                                                 const void *data,
                                                 mtev_skiplist_comparator_t comp) {
  mtev_skiplist_node *m, *p, *tmp, *ret = NULL, **stack;
  int nh=1, ch, stacki;
  if(!sl->top) {
    sl->height = 1;
    sl->top = sl->bottom = 
      calloc(1, sizeof(mtev_skiplist_node));
    sl->top->sl = sl;
  }
  if(sl->preheight) {
    while(nh < sl->preheight && get_b_rand()) nh++;
  } else {
    while(nh <= sl->height && get_b_rand()) nh++;
  }
  /* Now we have the new height at which we wish to insert our new node */
  /* Let us make sure that our tree is a least that tall (grow if necessary)*/
  for(;sl->height<nh;sl->height++) {
    sl->top->up = (mtev_skiplist_node *)calloc(1, sizeof(mtev_skiplist_node));
    sl->top->up->down = sl->top;
    sl->top = sl->top->up;
    sl->top->sl = sl;
  }
  ch = sl->height;
  /* Find the node (or node after which we would insert) */
  /* Keep a stack to pop back through for insertion */
  m = sl->top;
  stack = (mtev_skiplist_node **)alloca(sizeof(mtev_skiplist_node *)*(nh));
  stacki=0;
  while(m) {
    int compared=-1;
    if(m->next) compared=comp(data, m->next->data);
    if(compared == 0) {
      return 0;
    }
    if(compared<0) {
      if(ch<=nh) {
	/* push on stack */
	stack[stacki++] = m;
      }
      m = m->down;
      ch--;
    } else {
      m = m->next;
    }
  }
  /* Pop the stack and insert nodes */
  p = NULL;
  for(;stacki>0;stacki--) {
    m = stack[stacki-1];
    tmp = calloc(1, sizeof(*tmp));
    tmp->next = m->next;
    if(m->next) m->next->prev=tmp;
    tmp->prev = m;
    tmp->down = p;
    if(p) p->up=tmp;
    tmp->data = (void *)data;
    tmp->sl = sl;
    m->next = tmp;
    /* This sets ret to the bottom-most node we are inserting */
    if(!p) ret=tmp;
    p = tmp;
  }
  if(sl->index != NULL) {
    /* this is a external insertion, we must insert into each index as well */
    mtev_skiplist_node *p, *ni, *li;
    mtevAssert(ret);
    li=ret;
    for(p = mtev_skiplist_getlist(sl->index); p; mtev_skiplist_next(sl->index, &p)) {
      ni = mtev_skiplist_insert((mtev_skiplist *)p->data, ret->data);
      mtevAssert(ni);
      li->nextindex = ni;
      ni->previndex = li;
      li = ni;
    }
  }
  sl->size++;
  return ret;
}
コード例 #8
0
void noit_check_resolver_init() {
  int cnt;
  mtev_conf_section_t *servers, *searchdomains;
  eventer_t e;
  if(dns_init(NULL, 0) < 0)
    mtevL(noit_error, "dns initialization failed.\n");
  dns_ctx = dns_new(NULL);
  if(dns_init(dns_ctx, 0) != 0) {
    mtevL(noit_error, "dns initialization failed.\n");
    exit(-1);
  }

  /* Optional servers */
  servers = mtev_conf_get_sections(NULL, "//resolver//server", &cnt);
  if(cnt) {
    int i;
    char server[128];
    dns_add_serv(dns_ctx, NULL); /* reset */
    for(i=0;i<cnt;i++) {
      if(mtev_conf_get_stringbuf(servers[i], "self::node()",
                                 server, sizeof(server))) {
        if(dns_add_serv(dns_ctx, server) < 0) {
          mtevL(noit_error, "Failed adding DNS server: %s\n", server);
        }
      }
    }
    free(servers);
  }
  searchdomains = mtev_conf_get_sections(NULL, "//resolver//search", &cnt);
  if(cnt) {
    int i;
    char search[128];
    dns_add_srch(dns_ctx, NULL); /* reset */
    for(i=0;i<cnt;i++) {
      if(mtev_conf_get_stringbuf(searchdomains[i], "self::node()",
                                 search, sizeof(search))) {
        if(dns_add_srch(dns_ctx, search) < 0) {
          mtevL(noit_error, "Failed adding DNS search path: %s\n", search);
        }
        else if(dns_search_flag) dns_search_flag = 0; /* enable search */
      }
    }
    free(searchdomains);
  }

  if(mtev_conf_get_int(NULL, "//resolver/@ndots", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_NDOTS, cnt);

  if(mtev_conf_get_int(NULL, "//resolver/@ntries", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_NTRIES, cnt);

  if(mtev_conf_get_int(NULL, "//resolver/@timeout", &cnt))
    dns_set_opt(dns_ctx, DNS_OPT_TIMEOUT, cnt);

  if(dns_open(dns_ctx) < 0) {
    mtevL(noit_error, "dns open failed.\n");
    exit(-1);
  }
  eventer_name_callback("dns_cache_callback", dns_cache_callback);
  dns_set_tmcbck(dns_ctx, dns_cache_utm_fn, dns_ctx);
  e = eventer_alloc();
  e->mask = EVENTER_READ | EVENTER_EXCEPTION;
  e->closure = dns_ctx;
  e->callback = dns_cache_callback;
  e->fd = dns_sock(dns_ctx);
  eventer_add(e);

  mtev_skiplist_init(&nc_dns_cache);
  mtev_skiplist_set_compare(&nc_dns_cache, name_lookup, name_lookup_k);
  mtev_skiplist_add_index(&nc_dns_cache, refresh_idx, refresh_idx_k);

  /* maybe load it from cache */
  if(noit_resolver_cache_load_hook_exists()) {
    struct timeval now;
    char *key;
    void *data;
    int len;
    gettimeofday(&now, NULL);
    while(noit_resolver_cache_load_hook_invoke(&key, &data, &len) == MTEV_HOOK_CONTINUE) {
      dns_cache_node *n;
      n = calloc(1, sizeof(*n));
      if(dns_cache_node_deserialize(n, data, len) >= 0) {
        n->target = strdup(key);
        /* if the TTL indicates that it will expire in less than 60 seconds
         * (including stuff that should have already expired), then fudge
         * the last_updated time to make it expire some random time within
         * the next 60 seconds.
         */
        if(n->last_needed > now.tv_sec || n->last_updated > now.tv_sec)
          break; /* impossible */

        n->last_needed = now.tv_sec;
        if(n->last_updated + n->ttl < now.tv_sec + 60) {
          int fudge = MIN(60, n->ttl) + 1;
          n->last_updated = now.tv_sec - n->ttl + (lrand48() % fudge);
        }
        DCLOCK();
        mtev_skiplist_insert(&nc_dns_cache, n);
        DCUNLOCK();
        n = NULL;
      }
      else {
        mtevL(noit_error, "Failed to deserialize resolver cache record.\n");
      }
      if(n) dns_cache_node_free(n);
      if(key) free(key);
      if(data) free(data);
    }
  }

  noit_check_resolver_loop(NULL, 0, NULL, NULL);
  register_console_dns_cache_commands();

  mtev_hash_init(&etc_hosts_cache);
  noit_check_etc_hosts_cache_refresh(NULL, 0, NULL, NULL);
}
コード例 #9
0
static void dns_cache_resolve(struct dns_ctx *ctx, void *result, void *data,
                              enum dns_type rtype) {
  int ttl, acnt, r = dns_status(ctx), idnlen;
  dns_cache_node *n = data;
  unsigned char idn[DNS_MAXDN], dn[DNS_MAXDN];
  struct dns_parse p;
  struct dns_rr rr;
  unsigned nrr;
  struct in_addr *answers4;
  struct in6_addr *answers6;
  const unsigned char *pkt, *cur, *end;

  if(!result) goto blank;

  dns_dntodn(n->dn, idn, sizeof(idn));
  idnlen = dns_dnlen(idn);

  pkt = result; end = pkt + r; cur = dns_payload(pkt);
  dns_getdn(pkt, &cur, end, dn, sizeof(dn));
  dns_initparse(&p, NULL, pkt, cur, end);
  p.dnsp_qcls = 0;
  p.dnsp_qtyp = 0;
  nrr = 0;
  ttl = 0;

  while((r = dns_nextrr(&p, &rr)) > 0) {
    int dnlen = dns_dnlen(rr.dnsrr_dn);
    /* if we aren't searching and the don't match...
     * or if we are searching and the prefixes don't match...
     */
    if ((dns_search_flag && !dns_dnequal(idn, rr.dnsrr_dn)) ||
        (dns_search_flag == 0 &&
         (idnlen > dnlen || memcmp(idn, rr.dnsrr_dn, idnlen-1)))) continue;
    if (DNS_C_IN == rr.dnsrr_cls && rtype == rr.dnsrr_typ) ++nrr;
    else if (rr.dnsrr_typ == DNS_T_CNAME && !nrr) {
      if (dns_getdn(pkt, &rr.dnsrr_dptr, end,
                    p.dnsp_dnbuf, sizeof(p.dnsp_dnbuf)) <= 0 ||
          rr.dnsrr_dptr != rr.dnsrr_dend) {
        break;
      }
      else {
        if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
          ttl = rr.dnsrr_ttl;
        dns_dntodn(p.dnsp_dnbuf, idn, sizeof(idn));
        idnlen = dns_dnlen(idn);
      }
    }
  }
  if(!r && !nrr) goto blank;

  dns_rewind(&p, NULL);
  p.dnsp_qcls = DNS_C_IN;
  p.dnsp_qtyp = rtype;
  if(rtype == DNS_T_A)
    answers4 = calloc(nrr, sizeof(*answers4));
  else if(rtype == DNS_T_AAAA)
    answers6 = calloc(nrr, sizeof(*answers6));
  acnt = 0;
  while(dns_nextrr(&p, &rr) && nrr < MAX_RR) {
    int dnlen = dns_dnlen(rr.dnsrr_dn);
    if ((dns_search_flag && !dns_dnequal(idn, rr.dnsrr_dn)) ||
        (dns_search_flag == 0 &&
         (idnlen > dnlen || memcmp(idn, rr.dnsrr_dn, idnlen-1)))) continue;
    if (p.dnsp_rrl && !rr.dnsrr_dn[0] && rr.dnsrr_typ == DNS_T_OPT) continue;
    if (rtype == rr.dnsrr_typ) {
      if(rr.dnsrr_ttl > 0 && (ttl == 0 || rr.dnsrr_ttl < ttl))
        ttl = rr.dnsrr_ttl;
      switch(rr.dnsrr_typ) {
        case DNS_T_A:
          if(rr.dnsrr_dsz != 4) continue;
          memcpy(&answers4[acnt++], rr.dnsrr_dptr, rr.dnsrr_dsz);
          break;
        case DNS_T_AAAA:
          if(rr.dnsrr_dsz != 16) continue;
          memcpy(&answers6[acnt++], rr.dnsrr_dptr, rr.dnsrr_dsz);
          break;
        default:
          break;
      }
    }
  }

  n->ttl = ttl;
  if(rtype == DNS_T_A) {
    if(n->ip4) free(n->ip4);
    n->ip4_cnt = acnt;
    n->ip4 = answers4;
    n->lookup_inflight_v4 = mtev_false;
  }
  else if(rtype == DNS_T_AAAA) {
    if(n->ip6) free(n->ip6);
    n->ip6_cnt = acnt;
    n->ip6 = answers6;
    n->lookup_inflight_v6 = mtev_false;
  }
  else {
    if(result) free(result);
    return;
  }
  DCLOCK();
  mtev_skiplist_remove(&nc_dns_cache, n->target, NULL);
  n->last_updated = time(NULL);
  mtev_skiplist_insert(&nc_dns_cache, n);
  DCUNLOCK();
  mtevL(noit_debug, "Resolved %s/%s -> %d records\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")),
        acnt);
  if(result) free(result);
  return;

 blank:
  DCLOCK();
  if(rtype == DNS_T_A) blank_update_v4(n);
  if(rtype == DNS_T_AAAA) blank_update_v6(n);
  DCUNLOCK();
  mtevL(noit_debug, "Resolved %s/%s -> blank\n", n->target,
        (rtype == DNS_T_AAAA ? "IPv6" : (rtype == DNS_T_A ? "IPv4" : "???")));
  if(result) free(result);
  return;
}