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(!mtev_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); CONF_DIRTY(node); mtev_conf_mark_changed(); } return error; }
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; }
static int noit_filter_update_conf_rule(const char *fname, int idx, const char *rname, const char *value) { char xpath[1024]; xmlNodePtr rulenode, child; snprintf(xpath, sizeof(xpath), "//filtersets/filterset[@name=\"%s\"]/rule[%d]", fname, idx); rulenode = mtev_conf_get_section(NULL, xpath); if(!rulenode) return -1; child = xmlNewNode(NULL, (xmlChar *)rname); xmlNodeAddContent(child, (xmlChar *)value); xmlAddChild(rulenode, child); CONF_DIRTY(rulenode); mtev_conf_mark_changed(); mtev_conf_request_write(); return 0; }
static int noit_conf_mkcheck_under(const char *ppath, int argc, char **argv, uuid_t out) { int rv = -1; const char *path; char xpath[1024]; xmlXPathContextPtr xpath_ctxt = NULL; xmlXPathObjectPtr pobj = NULL; xmlNodePtr node = NULL, newnode; /* attr val [or] no attr (sets of two) */ if(argc % 2) goto out; mtev_conf_xml_xpath(NULL, &xpath_ctxt); path = strcmp(ppath, "/") ? ppath : ""; snprintf(xpath, sizeof(xpath), "/noit%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET || xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { goto out; } node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); if((newnode = xmlNewChild(node, NULL, (xmlChar *)"check", NULL)) != NULL) { char outstr[37]; uuid_generate(out); uuid_unparse_lower(out, outstr); xmlSetProp(newnode, (xmlChar *)"uuid", (xmlChar *)outstr); xmlSetProp(newnode, (xmlChar *)"disable", (xmlChar *)"true"); /* No risk of running off the end (we checked this above) */ if(noit_config_check_update_attrs(newnode, argc, argv)) { /* Something went wrong, remove the node */ xmlUnlinkNode(newnode); } else { CONF_DIRTY(newnode); mtev_conf_mark_changed(); rv = 0; } } out: if(pobj) xmlXPathFreeObject(pobj); return rv; }
static int replace_config(mtev_console_closure_t ncct, mtev_conf_t_userdata_t *info, const char *name, const char *value) { int i, cnt, rv = -1, active = 0; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; xmlNodePtr node, confignode; char xpath[1024], *path; path = info->path; if(!strcmp(path, "/")) path = ""; mtev_conf_xml_xpath(NULL, &xpath_ctxt); /* Only if checks will fixate this attribute shall we check for * child <check> nodes. * NOTE: this return nothing and "seems" okay if we are _in_ * a <check> node. That case is handled below. */ snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { uuid_t checkid; node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check && NOIT_CHECK_LIVE(check)) active++; } } if(pobj) xmlXPathFreeObject(pobj); #ifdef UNSAFE_RECONFIG snprintf(xpath, sizeof(xpath), "/noit/%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt != 1) { nc_printf(ncct, "Internal error: context node disappeared\n"); goto out; } node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); if(strcmp((const char *)node->name, "check")) { uuid_t checkid; /* Detect if we are actually a <check> node and attempting to * change something we shouldn't. * This is the counterpart noted above. */ if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(NOIT_CHECK_LIVE(check)) active++; } } if(active) { nc_printf(ncct, "Cannot set '%s', it would effect %d live check(s)\n", name, active); goto out; } if(pobj) xmlXPathFreeObject(pobj); #endif /* Here we want to remove /noit/path/config/name */ snprintf(xpath, sizeof(xpath), "/noit/%s/config/%s", path, name); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) > 0) { xmlNodePtr toremove; toremove = xmlXPathNodeSetItem(pobj->nodesetval, 0); CONF_REMOVE(toremove); xmlUnlinkNode(toremove); } /* TODO: if there are no more children of config, remove config? */ if(value) { if(pobj) xmlXPathFreeObject(pobj); /* He we create config if needed and place a child node under it */ snprintf(xpath, sizeof(xpath), "/noit/%s/config", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) == 0) { if(pobj) xmlXPathFreeObject(pobj); snprintf(xpath, sizeof(xpath), "/noit/%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; if(xmlXPathNodeSetGetLength(pobj->nodesetval) != 1) { nc_printf(ncct, "Node disappeared from under you!\n"); goto out; } confignode = xmlNewChild(xmlXPathNodeSetItem(pobj->nodesetval, 0), NULL, (xmlChar *)"config", NULL); if(confignode == NULL) { nc_printf(ncct, "Error creating config child node.\n"); goto out; } } else confignode = xmlXPathNodeSetItem(pobj->nodesetval, 0); mtevAssert(confignode); /* Now we create a child */ xmlNewChild(confignode, NULL, (xmlChar *)name, (xmlChar *)value); CONF_DIRTY(confignode); } mtev_conf_mark_changed(); rv = 0; out: if(pobj) xmlXPathFreeObject(pobj); return rv; }
static int noit_console_config_nocheck(mtev_console_closure_t ncct, int argc, char **argv, mtev_console_state_t *state, void *closure) { int i, cnt; const char *err = "internal error"; mtev_conf_t_userdata_t *info; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; char xpath[1024]; uuid_t checkid; mtev_conf_xml_xpath(NULL, &xpath_ctxt); if(argc < 1) { nc_printf(ncct, "requires one argument\n"); return -1; } info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA); if(noit_console_mkcheck_xpath(xpath, sizeof(xpath), info, argv[0])) { 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)) { err = "no checks found"; goto bad; } cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { xmlNodePtr node; char *uuid_conf; node = (mtev_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")); } else { if(argc > 1) { int j; for(j=1;j<argc;j++) xmlUnsetProp(node, (xmlChar *)argv[j]); noit_conf_check_bump_seq(node); CONF_DIRTY(node); } else { nc_printf(ncct, "descheduling %s\n", uuid_conf); noit_poller_deschedule(checkid, mtev_true); CONF_REMOVE(node); xmlUnlinkNode(node); } mtev_conf_mark_changed(); } xmlFree(uuid_conf); } if(argc > 1) { noit_poller_process_checks(xpath); noit_poller_reload(xpath); } nc_printf(ncct, "rebuilding causal map...\n"); noit_poller_make_causal_map(); if(pobj) xmlXPathFreeObject(pobj); return 0; bad: if(pobj) xmlXPathFreeObject(pobj); nc_printf(ncct, "%s\n", err); return -1; }
static int replace_attr(mtev_console_closure_t ncct, mtev_conf_t_userdata_t *info, struct _valid_attr_t *attrinfo, const char *value) { int i, cnt, rv = -1, active = 0; xmlXPathObjectPtr pobj = NULL; xmlXPathContextPtr xpath_ctxt = NULL; xmlNodePtr node; char xpath[1024], *path; path = info->path; if(!strcmp(path, "/")) path = ""; mtev_conf_xml_xpath(NULL, &xpath_ctxt); if(attrinfo->checks_fixate) { /* Only if checks will fixate this attribute shall we check for * child <check> nodes. * NOTE: this return nothing and "seems" okay if we are _in_ * a <check> node. That case is handled below. */ snprintf(xpath, sizeof(xpath), "/noit/%s//check[@uuid]", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); for(i=0; i<cnt; i++) { uuid_t checkid; node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, i); if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check && NOIT_CHECK_LIVE(check)) active++; } } if(pobj) xmlXPathFreeObject(pobj); } snprintf(xpath, sizeof(xpath), "/noit/%s", path); pobj = xmlXPathEval((xmlChar *)xpath, xpath_ctxt); if(!pobj || pobj->type != XPATH_NODESET) goto out; cnt = xmlXPathNodeSetGetLength(pobj->nodesetval); if(cnt != 1) { nc_printf(ncct, "Internal error: context node disappeared\n"); goto out; } node = (mtev_conf_section_t)xmlXPathNodeSetItem(pobj->nodesetval, 0); if(attrinfo->checks_fixate && !strcmp((const char *)node->name, "check")) { uuid_t checkid; /* Detect if we are actually a <check> node and attempting to * change something we shouldn't. * This is the counterpart noted above. */ if(mtev_conf_get_uuid(node, "@uuid", checkid)) { noit_check_t *check; check = noit_poller_lookup(checkid); if(check && NOIT_CHECK_LIVE(check)) active++; } } if(active) { nc_printf(ncct, "Cannot set '%s', it would effect %d live check(s)\n", attrinfo->name, active); goto out; } xmlUnsetProp(node, (xmlChar *)attrinfo->name); if(value) xmlSetProp(node, (xmlChar *)attrinfo->name, (xmlChar *)value); if(!strcmp((const char *)node->name, "check")) noit_conf_check_bump_seq(node); CONF_DIRTY(node); mtev_conf_mark_changed(); rv = 0; out: if(pobj) xmlXPathFreeObject(pobj); return rv; }
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; }