예제 #1
0
static xmlNodePtr
make_conf_path(char *path) {
  xmlNodePtr start, tmp;
  char fullpath[1024], *tok, *brk;
  if(!path || strlen(path) < 1) return NULL;
  snprintf(fullpath, sizeof(fullpath), "%s", path+1);
  fullpath[strlen(fullpath)-1] = '\0';
  start = noit_conf_get_section(NULL, "/noit/filtersets");
  if(!start) return NULL;
  for (tok = strtok_r(fullpath, "/", &brk);
       tok;
       tok = strtok_r(NULL, "/", &brk)) {
    if(!xmlValidateNameValue((xmlChar *)tok)) return NULL;
    if(!strcmp(tok, "filterset")) return NULL;
    for (tmp = start->children; tmp; tmp = tmp->next) {
      if(!strcmp((char *)tmp->name, tok)) break;
    }
    if(!tmp) {
      tmp = xmlNewNode(NULL, (xmlChar *)tok);
      xmlAddChild(start, tmp);
      CONF_DIRTY(tmp);
    }
    start = tmp;
  }
  return start;
}
예제 #2
0
static int
noit_console_filter_show(noit_console_closure_t ncct,
                         int argc, char **argv,
                         noit_console_state_t *state,
                         void *closure) {
  noit_conf_t_userdata_t *info;
  char xpath[1024];
  xmlNodePtr fsnode;
  noit_conf_section_t *rules;
  int i, rulecnt;

  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA);
  snprintf(xpath, sizeof(xpath), "/%s",
           info->path);
  fsnode = noit_conf_get_section(NULL, xpath);
  if(!fsnode) {
    nc_printf(ncct, "internal error\n");
    return -1;
  }
  rules = noit_conf_get_sections(fsnode, "rule", &rulecnt);
  for(i=0; i<rulecnt; i++) {
    char val[256];
    val[0] = '\0';
    noit_conf_get_stringbuf(rules[i], "@type", val, sizeof(val));
    nc_printf(ncct, "Rule %d [%s]:\n", i+1, val);
#define DUMP_ATTR(a) do { \
  char *vstr; \
  noit_conf_section_t ht; \
  int cnt; \
  ht = noit_conf_get_sections(rules[i], #a, &cnt); \
  if(ht && cnt) { \
    nc_printf(ncct, "\t%s: hash match of %d items\n", #a, cnt); \
  } \
  else if(noit_conf_get_string(rules[i], "@" #a, &vstr)) { \
    nc_printf(ncct, "\t%s: /%s/\n", #a, val); \
    free(vstr); \
  } \
  free(ht); \
} while(0)
    DUMP_ATTR(target);
    DUMP_ATTR(module);
    DUMP_ATTR(name);
    DUMP_ATTR(metric);
  }
  if(rules) free(rules);
  return 0;
}
예제 #3
0
noit_check_t *
noit_check_watch(uuid_t in, int period) {
  /* First look for a copy that is being watched */
  int minimum_pi = 1000, granularity_pi = 500;
  noit_conf_section_t check_node;
  char uuid_str[UUID_STR_LEN + 1];
  char xpath[1024];
  noit_check_t n, *f;

  uuid_unparse_lower(in, uuid_str);
  /* Find the check */
  snprintf(xpath, sizeof(xpath), "//checks//check[@uuid=\"%s\"]", uuid_str);
  check_node = noit_conf_get_section(NULL, xpath);
  noit_conf_get_int(NULL, "//checks/@transient_min_period", &minimum_pi);
  noit_conf_get_int(NULL, "//checks/@transient_period_granularity", &granularity_pi);
  if(check_node) {
    noit_conf_get_int(check_node,
                      "ancestor-or-self::node()/@transient_min_period",
                      &minimum_pi);
    noit_conf_get_int(check_node,
                      "ancestor-or-self::node()/@transient_period_granularity",
                      &granularity_pi);
  }

  /* apply the bounds */
  period /= granularity_pi;
  period *= granularity_pi;
  period = MAX(period, minimum_pi);

  uuid_copy(n.checkid, in);
  n.period = period;

  f = noit_skiplist_find(&watchlist, &n, NULL);
  if(f) return f;
  f = noit_check_clone(in);
  if(!f) return NULL;
  f->period = period;
  f->timeout = period - 10;
  f->flags |= NP_TRANSIENT;
  noitL(noit_debug, "Watching %s@%d\n", uuid_str, period);
  noit_skiplist_insert(&watchlist, f);
  return f;
}
예제 #4
0
static int
rest_show_filter(noit_http_rest_closure_t *restc,
                 int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlDocPtr doc = NULL;
  xmlNodePtr node, root;
  char xpath[1024];
  int error_code = 500;

  if(npats != 2) goto error;

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);

  node = noit_conf_get_section(NULL, xpath);
  if(!node) goto not_found;

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlCopyNode(node, 1);
  xmlDocSetRootElement(doc, root);
  noit_http_response_ok(ctx, "text/xml");
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
예제 #5
0
static int
rest_delete_filter(noit_http_rest_closure_t *restc,
                   int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlNodePtr node;
  char xpath[1024];
  int error_code = 500;

  if(npats != 2) goto error;

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);
  node = noit_conf_get_section(NULL, xpath);
  if(!node) goto not_found;
  if(noit_filter_remove(node) == 0) goto not_found;
  CONF_REMOVE(node);
  xmlUnlinkNode(node);
  xmlFreeNode(node);

  if(noit_conf_write_file(NULL) != 0)
    noitL(noit_error, "local config write failed\n");
  noit_conf_mark_changed();
  noit_http_response_ok(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 not_found:
  noit_http_response_not_found(ctx, "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  return 0;
}
예제 #6
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;
}
예제 #7
0
static int
noit_console_rule_configure(noit_console_closure_t ncct,
                            int argc, char **argv,
                            noit_console_state_t *state,
                            void *closure) {
  xmlNodePtr fsnode = NULL;
  noit_conf_t_userdata_t *info;
  char xpath[1024];

  info = noit_console_userdata_get(ncct, NOIT_CONF_T_USERDATA);
  snprintf(xpath, sizeof(xpath), "/%s",
           info->path);
  fsnode = noit_conf_get_section(NULL, xpath);
  if(!fsnode) {
    nc_printf(ncct, "internal error");
    return -1;
  }
  if(closure) {
    int rulenum;
    xmlNodePtr byebye;
    /* removing a rule */
    if(argc != 1) {
      nc_printf(ncct, "requires one argument\n");
      return -1;
    }
    rulenum = atoi(argv[0]);
    snprintf(xpath, sizeof(xpath), "rule[%d]", rulenum);
    byebye = noit_conf_get_section(fsnode, xpath);
    if(!byebye) {
      nc_printf(ncct, "cannot find rule\n");
      return -1;
    }
    xmlUnlinkNode(byebye);
    xmlFreeNode(byebye);
    nc_printf(ncct, "removed\n");
  }
  else {
    xmlNodePtr (*add_func)(xmlNodePtr, xmlNodePtr);
    xmlNodePtr add_arg, new_rule;
    int i, needs_type = 1;
    if(argc < 1 || argc % 2) {
      nc_printf(ncct, "even number of arguments required\n");
      return -1;
    }
    if(!strcmp(argv[0], "before") || !strcmp(argv[0], "after")) {
      int rulenum = atoi(argv[1]);
      snprintf(xpath, sizeof(xpath), "rule[%d]", rulenum);
      add_arg = noit_conf_get_section(fsnode, xpath);
      if(!add_arg) {
        nc_printf(ncct, "%s rule not found\n", xpath);
        return -1;
      }
      if(*argv[0] == 'b') add_func = xmlAddPrevSibling;
      else add_func = xmlAddNextSibling;
      argc -= 2;
      argv += 2;
    }
    else {
      add_func = xmlAddChild;
      add_arg = fsnode;
    }
    for(i=0;i<argc;i+=2) {
      if(!strcmp(argv[i], "type")) needs_type = 0;
      else if(strcmp(argv[i], "target") && strcmp(argv[i], "module") &&
              strcmp(argv[i], "name") && strcmp(argv[i], "metric")) {
        nc_printf(ncct, "unknown attribute '%s'\n", argv[i]);
        return -1;
      }
    }
    if(needs_type) {
      nc_printf(ncct, "type <allow|deny> is required\n");
      return -1;
    }
    new_rule = xmlNewNode(NULL, (xmlChar *)"rule");
    for(i=0;i<argc;i+=2)
      xmlSetProp(new_rule, (xmlChar *)argv[i], (xmlChar *)argv[i+1]);
    add_func(add_arg, new_rule);
    noit_filter_compile_add((noit_conf_section_t *)fsnode);
  }
  return 0;
}
예제 #8
0
noit_check_t *
noit_fire_check(xmlNodePtr attr, xmlNodePtr config, const char **error) {
  char *target = NULL, *name = NULL, *module = NULL, *filterset = NULL;
  char *resolve_rtype = NULL;
  int timeout = 0, flags = NP_TRANSIENT, i, mod_cnt;
  noit_module_t *m;
  noit_check_t *c = NULL;
  xmlNodePtr a, co;
  noit_hash_table *conf_hash = NULL;
  noit_hash_table **moptions = NULL;

  for(a = attr->children; a; a = a->next) {
    if(!strcmp((char *)a->name, "target"))
      target = (char *)xmlNodeGetContent(a);
    else if(!strcmp((char *)a->name, "name"))
      name = (char *)xmlNodeGetContent(a);
    else if(!strcmp((char *)a->name, "module"))
      module = (char *)xmlNodeGetContent(a);
    else if(!strcmp((char *)a->name, "filterset"))
      filterset = (char *)xmlNodeGetContent(a);
    else if(!strcmp((char *)a->name, "timeout")) {
      char *timeout_str = (char *)xmlNodeGetContent(a);
      timeout = atoi(timeout_str);
      free(timeout_str);
    } else if(!strcmp((char *)a->name, "resolve_rtype")) 
      resolve_rtype = (char *)xmlNodeGetContent(a);
  }
  m = noit_module_lookup(module);
  if(!m) {
    *error = "cannot find requested module";
    goto error;
  }
  conf_hash = calloc(1, sizeof(*conf_hash));
  if(config) {
    for(co = config->children; co; co = co->next) {
      char *name, *val;
      xmlChar *tmp_val;
      name = strdup((char *)co->name);
      tmp_val = xmlNodeGetContent(co);
      val = strdup(tmp_val ? (char *)tmp_val : "");
      noit_hash_replace(conf_hash, name, strlen(name), val, free, free);
      xmlFree(tmp_val);
    }
  }
  mod_cnt = noit_check_registered_module_cnt();
  if(mod_cnt > 0) {
    moptions = alloca(mod_cnt * sizeof(*moptions));
    memset(moptions, 0, mod_cnt * sizeof(*moptions));
    for(i=0; i<mod_cnt; i++) {
      const char *name;
      noit_conf_section_t checks;
      name = noit_check_registered_module(i);
      checks = noit_conf_get_section(NULL, "/noit/checks");
      if(name) moptions[i] = noit_conf_get_namespaced_hash(checks, "config", name);
    }
  }
  if(!m->initiate_check) {
    *error = "that module cannot run checks";
    goto error;
  }
  flags |= noit_calc_rtype_flag(resolve_rtype);
  c = calloc(1, sizeof(*c));
  noit_check_update(c, target, name, filterset,
                    conf_hash, moptions, 0, timeout, NULL, flags);
  c->module = strdup(module);
  uuid_generate(c->checkid);
  c->flags |= NP_DISABLED; /* this is hack to know we haven't run it yet */
  if(NOIT_CHECK_SHOULD_RESOLVE(c))
    noit_check_resolve(c);

 error:
  if(conf_hash) {
    noit_hash_destroy(conf_hash, free, free);
    free(conf_hash);
  }
  if(moptions) {
    for(i=0; i<mod_cnt; i++) {
      if(moptions[i]) {
        noit_hash_destroy(moptions[i], free, free);
        free(moptions[i]);
      }
    }
  }
  if(target) xmlFree(target);
  if(name) xmlFree(name);
  if(module) xmlFree(module);
  if(filterset) xmlFree(filterset);
  if (resolve_rtype) xmlFree(resolve_rtype);
  return c;
}
예제 #9
0
static int
rest_set_filter(noit_http_rest_closure_t *restc,
                int npats, char **pats) {
  noit_http_session_ctx *ctx = restc->http_ctx;
  xmlDocPtr doc = NULL, indoc = NULL;
  xmlNodePtr node, parent, root, newfilter;
  char xpath[1024];
  int error_code = 500, complete = 0, mask = 0;
  const char *error = "internal error";

  if(npats != 2) goto error;

  indoc = rest_get_xml_upload(restc, &mask, &complete);
  if(!complete) return mask;
  if(indoc == NULL) FAIL("xml parse error");

  snprintf(xpath, sizeof(xpath), "//filtersets%sfilterset[@name=\"%s\"]",
           pats[0], pats[1]);
  node = noit_conf_get_section(NULL, xpath);
  if(!node && noit_filter_exists(pats[1])) {
    /* It's someone else's */
    error_code = 403;
    goto error;
  }

  if((newfilter = validate_filter_post(indoc)) == NULL) goto error;
  xmlSetProp(newfilter, (xmlChar *)"name", (xmlChar *)pats[1]);

  parent = make_conf_path(pats[0]);
  if(!parent) FAIL("invalid path");
  if(node) {
    xmlUnlinkNode(node);
    xmlFreeNode(node);
  }
  xmlUnlinkNode(newfilter);
  xmlAddChild(parent, newfilter);
  CONF_DIRTY(newfilter);

  noit_conf_mark_changed();
  if(noit_conf_write_file(NULL) != 0)
    noitL(noit_error, "local config write failed\n");
  noit_filter_compile_add(newfilter);
  if(restc->call_closure_free) restc->call_closure_free(restc->call_closure);
  restc->call_closure_free = NULL;
  restc->call_closure = NULL;
  restc->fastpath = rest_show_filter;
  return restc->fastpath(restc, restc->nparams, restc->params);

 error:
  noit_http_response_standard(ctx, error_code, "ERROR", "text/html");
  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlNewDocNode(doc, NULL, (xmlChar *)"error", NULL);
  xmlDocSetRootElement(doc, root);
  xmlNodeAddContent(root, (xmlChar *)error);
  noit_http_response_xml(ctx, doc);
  noit_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}