Пример #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 = mtev_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
void
noit_jlog_listener_init() {
  xmlNodePtr node;
  eventer_name_callback("log_transit/1.0", noit_jlog_handler);
  mtev_control_dispatch_delegate(mtev_control_dispatch,
                                 NOIT_JLOG_DATA_FEED,
                                 noit_jlog_handler);
  mtev_control_dispatch_delegate(mtev_control_dispatch,
                                 NOIT_JLOG_DATA_TEMP_FEED,
                                 noit_jlog_handler);
  node = mtev_conf_get_section(NULL, "//logs");
  if (node) {
    mtev_conf_get_int(node, "//jlog/max_msg_batch_lines", &MAX_ROWS_AT_ONCE);
    mtev_conf_get_int(node, "//jlog/default_mseconds_between_batches", &DEFAULT_MSECONDS_BETWEEN_BATCHES);
    mtev_conf_get_int(node, "//jlog/default_transient_mseconds_between_batches", &DEFAULT_TRANSIENT_MSECONDS_BETWEEN_BATCHES);
  }
  mtevAssert(mtev_http_rest_register_auth(
    "GET", "/", "^feed$",
    rest_show_feed, mtev_http_rest_client_cert_auth
  ) == 0);
  mtevAssert(mtev_http_rest_register_auth(
    "DELETE", "/feed/", "^(.+)$",
    rest_delete_feed, mtev_http_rest_client_cert_auth
  ) == 0);
  mtevAssert(mtev_http_rest_register_auth(
    "PUT", "/", "^feed$",
    rest_add_feed, mtev_http_rest_client_cert_auth
  ) == 0);
}
Пример #3
0
static int
child_main() {
  int log_flags;
  mtev_conf_section_t section;
  char *err = NULL;

  cli_stdout = mtev_log_stream_new_on_fd("stdout", 1, NULL);

  log_flags = mtev_log_stream_get_flags(mtev_stderr);
  log_flags &= ~(MTEV_LOG_STREAM_FACILITY|MTEV_LOG_STREAM_TIMESTAMPS);
  mtev_log_stream_set_flags(mtev_stderr, log_flags);

  /* reload our config, to make sure we have the most current */
  if(mtev_conf_load(NULL) == -1) {
    mtevL(mtev_error, "Cannot load config: '%s'\n", config_file);
    if(needs_unlink) unlink(config_file);
    exit(2);
  }

  mtev_conf_security_init(APPNAME, droptouser, droptogroup, NULL);

  if(mtev_conf_write_file(&err) != 0) {
    if(err) {
      mtevL(mtev_stderr, "Error: '%s'\n", err);
      free(err);
    }
    mtevL(mtev_stderr, "Permissions issue, are you running as the right user?\n");
    exit(2);
  }
  if(needs_unlink) unlink(config_file);

  /* update the lua module */
  section = mtev_conf_get_section(NULL, "/cli/modules/generic[@name=\"lua_general\"]/config");
  if(!section || !mtev_conf_set_string(section, "lua_module", lua_file)) {
    mtevL(mtev_stderr, "Cannot set target lua module, invalid config.\n");
    exit(2);
  }

  eventer_init();
  mtev_dso_init();
  mtev_dso_post_init();
  if(mtev_dso_load_failures() > 0) {
    mtevL(mtev_stderr, "Failed to initialize.\n");
    exit(2);
  }

  if(interactive) {
    mtev_console_init(APPNAME);
    mtev_console_conf_init(APPNAME);
    eventer_set_fd_nonblocking(STDIN_FILENO);
    if(mtev_console_std_init(STDIN_FILENO, STDOUT_FILENO)) {
      mtevL(mtev_stderr, "Failed to initialize IO\n");
      exit(2);
    }
  }
  /* Lastly, spin up the event loop */
  eventer_loop();
  return 0;
}
Пример #4
0
static int
noit_console_filter_show(mtev_console_closure_t ncct,
                         int argc, char **argv,
                         mtev_console_state_t *state,
                         void *closure) {
  mtev_conf_t_userdata_t *info;
  char xpath[1024];
  xmlNodePtr fsnode;
  mtev_conf_section_t *rules;
  int i, rulecnt;

  info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA);
  snprintf(xpath, sizeof(xpath), "/%s",
           info->path);
  fsnode = mtev_conf_get_section(NULL, xpath);
  if(!fsnode) {
    nc_printf(ncct, "internal error\n");
    return -1;
  }
  rules = mtev_conf_get_sections(fsnode, "rule", &rulecnt);
  for(i=0; i<rulecnt; i++) {
    char val[256];
    val[0] = '\0';
    mtev_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; \
  mtev_conf_section_t ht; \
  int cnt; \
  ht = mtev_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(mtev_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);
    DUMP_ATTR(id);
    DUMP_ATTR(skipto);
  }
  if(rules) free(rules);
  return 0;
}
Пример #5
0
static mtev_hook_return_t
noit_delete_section_impl(void *closure, const char *root, const char *path,
                         const char *name, const char **err) {
  mtev_hook_return_t rv = MTEV_HOOK_CONTINUE;
  char xpath[1024];
  mtev_conf_section_t exists = NULL;

  snprintf(xpath, sizeof(xpath), "/%s%s/%s//check", root, path, name);
  exists = mtev_conf_get_section(NULL, xpath);
  if(exists) {
    if(err) *err = "cannot delete section, has checks";
    rv = MTEV_HOOK_ABORT;
  }
  return rv;
}
Пример #6
0
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;
}
Пример #7
0
static int
rest_show_filter(mtev_http_rest_closure_t *restc,
                 int npats, char **pats) {
  mtev_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 = mtev_conf_get_section(NULL, xpath);
  if(!node) goto not_found;

  doc = xmlNewDoc((xmlChar *)"1.0");
  root = xmlCopyNode(node, 1);
  xmlDocSetRootElement(doc, root);
  mtev_http_response_ok(ctx, "text/xml");
  mtev_http_response_xml(ctx, doc);
  mtev_http_response_end(ctx);
  goto cleanup;

 not_found:
  mtev_http_response_not_found(ctx, "text/html");
  mtev_http_response_end(ctx);
  goto cleanup;

 error:
  mtev_http_response_standard(ctx, error_code, "ERROR", "text/html");
  mtev_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
Пример #8
0
static int
rest_delete_filter(mtev_http_rest_closure_t *restc,
                   int npats, char **pats) {
  mtev_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 = mtev_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(mtev_conf_write_file(NULL) != 0)
    mtevL(noit_error, "local config write failed\n");
  mtev_conf_mark_changed();
  mtev_http_response_ok(ctx, "text/html");
  mtev_http_response_end(ctx);
  goto cleanup;

 not_found:
  mtev_http_response_not_found(ctx, "text/html");
  mtev_http_response_end(ctx);
  goto cleanup;

 error:
  mtev_http_response_standard(ctx, error_code, "ERROR", "text/html");
  mtev_http_response_end(ctx);
  goto cleanup;

 cleanup:
  return 0;
}
Пример #9
0
int
mtev_main(const char *appname,
          const char *config_filename, int debug, int foreground,
          mtev_lock_op_t lock, const char *_glider,
          const char *drop_to_user, const char *drop_to_group,
          int (*passed_child_main)(void)) {
    mtev_conf_section_t watchdog_conf;
    int fd, lockfd, watchdog_timeout = 0, rv;
    int wait_for_lock;
    char conf_str[1024];
    char lockfile[PATH_MAX];
    char *trace_dir = NULL;
    char appscratch[1024];
    char *glider = (char *)_glider;
    char *watchdog_timeout_str;
    int retry_val;
    int span_val;
    int ret;
    int cnt;
    mtev_conf_section_t root;

    wait_for_lock = (lock == MTEV_LOCK_OP_WAIT) ? 1 : 0;

    mtev_init_globals();

    char *require_invariant_tsc = getenv("MTEV_RDTSC_REQUIRE_INVARIANT");
    if (require_invariant_tsc && strcmp(require_invariant_tsc, "0") == 0) {
        mtev_time_toggle_require_invariant_tsc(mtev_false);
    }

    char *disable_rdtsc = getenv("MTEV_RDTSC_DISABLE");
    if (disable_rdtsc && strcmp(disable_rdtsc, "1") == 0) {
        mtev_time_toggle_tsc(mtev_false);
    }

    char *disable_binding = getenv("MTEV_THREAD_BINDING_DISABLE");
    if (disable_binding && strcmp(disable_binding, "1") == 0) {
        mtev_thread_disable_binding();
    }

    /* First initialize logging, so we can log errors */
    mtev_log_init(debug);
    mtev_log_stream_add_stream(mtev_debug, mtev_stderr);
    mtev_log_stream_add_stream(mtev_error, mtev_stderr);
    mtev_log_stream_add_stream(mtev_notice, mtev_error);

    /* Next load the configs */
    mtev_conf_use_namespace(appname);
    mtev_conf_init(appname);
    if(mtev_conf_load(config_filename) == -1) {
        fprintf(stderr, "Cannot load config: '%s'\n", config_filename);
        exit(-1);
    }

    char* root_section_path = alloca(strlen(appname)+2);
    sprintf(root_section_path, "/%s", appname);
    root = mtev_conf_get_sections(NULL, root_section_path, &cnt);
    free(root);
    if(cnt==0) {
        fprintf(stderr, "The config must have <%s> as its root node\n", appname);
        exit(-1);
    }

    /* Reinitialize the logging system now that we have a config */
    mtev_conf_log_init(appname, drop_to_user, drop_to_group);
    if(debug) {
        mtev_log_stream_set_flags(mtev_debug, mtev_log_stream_get_flags(mtev_debug) | MTEV_LOG_STREAM_ENABLED);
    }
    cli_log_switches();

    snprintf(appscratch, sizeof(appscratch), "/%s/watchdog|/%s/include/watchdog", appname, appname);
    watchdog_conf = mtev_conf_get_section(NULL, appscratch);

    if(!glider) (void) mtev_conf_get_string(watchdog_conf, "@glider", &glider);
    if(mtev_watchdog_glider(glider)) {
        mtevL(mtev_stderr, "Invalid glider, exiting.\n");
        exit(-1);
    }
    (void)mtev_conf_get_string(watchdog_conf, "@tracedir", &trace_dir);
    if(trace_dir) {
        if(mtev_watchdog_glider_trace_dir(trace_dir)) {
            mtevL(mtev_stderr, "Invalid glider tracedir, exiting.\n");
            exit(-1);
        }
    }

    ret = mtev_conf_get_int(watchdog_conf, "@retries", &retry_val);
    if((ret == 0) || (retry_val == 0)) {
        retry_val = 5;
    }
    ret = mtev_conf_get_int(watchdog_conf, "@span", &span_val);
    if((ret == 0) || (span_val == 0)) {
        span_val = 60;
    }

    mtev_watchdog_ratelimit(retry_val, span_val);

    /* Lastly, run through all other system inits */
    snprintf(appscratch, sizeof(appscratch), "/%s/eventer/@implementation", appname);
    if(!mtev_conf_get_stringbuf(NULL, appscratch, conf_str, sizeof(conf_str))) {
        mtevL(mtev_stderr, "Cannot find '%s' in configuration\n", appscratch);
        exit(-1);
    }
    if(eventer_choose(conf_str) == -1) {
        mtevL(mtev_stderr, "Cannot choose eventer %s\n", conf_str);
        exit(-1);
    }
    if(configure_eventer(appname) != 0) {
        mtevL(mtev_stderr, "Cannot configure eventer\n");
        exit(-1);
    }

    mtev_watchdog_prefork_init();

    if(foreground != 1 && chdir("/") != 0) {
        mtevL(mtev_stderr, "Failed chdir(\"/\"): %s\n", strerror(errno));
        exit(-1);
    }

    /* Acquire the lock so that we can throw an error if it doesn't work.
     * If we've started -D, we'll have the lock.
     * If not we will daemon and must reacquire the lock.
     */
    lockfd = -1;
    lockfile[0] = '\0';
    snprintf(appscratch, sizeof(appscratch), "/%s/@lockfile", appname);
    if(lock != MTEV_LOCK_OP_NONE &&
            mtev_conf_get_stringbuf(NULL, appscratch,
                                    lockfile, sizeof(lockfile))) {
        do {
            if((lockfd = mtev_lockfile_acquire(lockfile)) < 0) {
                if(!wait_for_lock) {
                    mtevL(mtev_stderr, "Failed to acquire lock: %s\n", lockfile);
                    exit(-1);
                }
                if(wait_for_lock == 1) {
                    mtevL(mtev_stderr, "%d failed to acquire lock(%s), waiting...\n",
                          (int)getpid(), lockfile);
                    wait_for_lock++;
                }
                usleep(1000);
            }
            else {
                if(wait_for_lock > 1) mtevL(mtev_stderr, "Lock acquired proceeding.\n");
                wait_for_lock = 0;
            }
        } while(wait_for_lock);
    }

    if(foreground == 1) {
        mtev_time_start_tsc();
        mtevL(mtev_notice, "%s booting [unmanaged]\n", appname);
        int rv = passed_child_main();
        mtev_lockfile_release(lockfd);
        return rv;
    }

    watchdog_timeout_str = getenv("WATCHDOG_TIMEOUT");
    if(watchdog_timeout_str) {
        watchdog_timeout = atoi(watchdog_timeout_str);
        mtevL(mtev_error, "Setting watchdog timeout to %d\n",
              watchdog_timeout);
    }

    /* This isn't inherited across forks... */
    if(lockfd >= 0) mtev_lockfile_release(lockfd);
    lockfd = -1;

    if(foreground == 0) {
        fd = open("/dev/null", O_RDONLY);
        if(fd < 0 || dup2(fd, STDIN_FILENO) < 0) {
            fprintf(stderr, "Failed to setup stdin: %s\n", strerror(errno));
            exit(-1);
        }
        close(fd);
        fd = open("/dev/null", O_WRONLY);
        if(fd < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0) {
            fprintf(stderr, "Failed to setup std{out,err}: %s\n", strerror(errno));
            exit(-1);
        }
        close(fd);

        if(fork()) exit(0);
        setsid();
        if(fork()) exit(0);
    }

    /* Reacquire the lock */
    if(*lockfile) {
        if (lock) {
            if((lockfd = mtev_lockfile_acquire(lockfile)) < 0) {
                mtevL(mtev_stderr, "Failed to acquire lock: %s\n", lockfile);
                exit(-1);
            }
        }
    }

    signal(SIGHUP, SIG_IGN);
    mtevL(mtev_notice, "%s booting\n", appname);
    rv = mtev_watchdog_start_child(appname, passed_child_main, watchdog_timeout);
    mtev_lockfile_release(lockfd);
    return rv;
}
Пример #10
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 = NULL;
  noit_check_t *c = NULL;
  xmlNodePtr a, co;
  mtev_hash_table *conf_hash = NULL;
  mtev_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);
  }
  if(!noit_check_validate_target(target)) {
    *error = "malformed target";
    goto error;
  }
  if(!noit_check_validate_name(name)) {
    *error = "malformed name";
    goto error;
  }
  if(module) 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 : "");
      mtev_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;
      mtev_conf_section_t checks;
      name = noit_check_registered_module(i);
      checks = mtev_conf_get_section(NULL, "/noit/checks");
      if(name) moptions[i] = mtev_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 = mtev_memory_safe_calloc(1, sizeof(*c));
  c->module = strdup(module);
  c->flags = NP_TRANSIENT;
  noit_check_update(c, target, name, filterset,
                    conf_hash, moptions, 0, timeout, NULL, 0, flags);
  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) {
    mtev_hash_destroy(conf_hash, free, free);
    free(conf_hash);
  }
  if(moptions) {
    for(i=0; i<mod_cnt; i++) {
      if(moptions[i]) {
        mtev_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;
}
Пример #11
0
static int
rest_set_filter(mtev_http_rest_closure_t *restc,
                int npats, char **pats) {
  mtev_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 = mtev_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);

  mtev_conf_mark_changed();
  if(mtev_conf_write_file(NULL) != 0)
    mtevL(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:
  mtev_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);
  mtev_http_response_xml(ctx, doc);
  mtev_http_response_end(ctx);
  goto cleanup;

 cleanup:
  if(doc) xmlFreeDoc(doc);
  return 0;
}
Пример #12
0
static int
noit_console_filter_configure(mtev_console_closure_t ncct,
                              int argc, char **argv,
                              mtev_console_state_t *state,
                              void *closure) {
  xmlNodePtr parent, fsnode = NULL;
  int rv = -1;
  mtev_conf_t_userdata_t *info;
  char xpath[1024];

  info = mtev_console_userdata_get(ncct, MTEV_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 = mtev_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 = mtev_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) {
      CONF_REMOVE(fsnode);
      xmlUnlinkNode(fsnode);
      xmlFreeNode(fsnode);
    }
    rv = !removed;
    goto cleanup;
  }
  if(!fsnode) {
    void *vfs;
    nc_printf(ncct, "Cannot find filterset '%s'\n", argv[0]);
    LOCKFS();
    if(mtev_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;
    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) {
      mtev_console_state_push_state(ncct, state);
      mtev_console_state_init(ncct);
    }
  }
 cleanup:
  return rv;
}
Пример #13
0
static int
noit_console_rule_configure(mtev_console_closure_t ncct,
                            int argc, char **argv,
                            mtev_console_state_t *state,
                            void *closure) {
  xmlNodePtr fsnode = NULL;
  mtev_conf_t_userdata_t *info;
  char xpath[1024];

  info = mtev_console_userdata_get(ncct, MTEV_CONF_T_USERDATA);
  snprintf(xpath, sizeof(xpath), "/%s",
           info->path);
  fsnode = mtev_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 = mtev_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 = mtev_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") &&
              strcmp(argv[i], "id")) {
        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((mtev_conf_section_t *)fsnode);
  }
  return 0;
}